Vendor import of llvm-project branch release/19.x llvmorg-19.1.0-rc1-0-ga4902a36d5c2.
This commit is contained in:
@@ -942,6 +942,9 @@ def warn_ptrauth_auth_null_pointer :
|
||||
InGroup<PtrAuthNullPointers>;
|
||||
def err_ptrauth_string_not_literal : Error<
|
||||
"argument must be a string literal%select{| of char type}0">;
|
||||
def err_ptrauth_type_disc_undiscriminated : Error<
|
||||
"cannot pass undiscriminated type %0 to "
|
||||
"'__builtin_ptrauth_type_discriminator'">;
|
||||
|
||||
def note_ptrauth_virtual_function_pointer_incomplete_arg_ret :
|
||||
Note<"cannot take an address of a virtual member function if its return or "
|
||||
|
||||
@@ -596,6 +596,8 @@ ALIAS("__is_same_as", __is_same, KEYCXX)
|
||||
KEYWORD(__private_extern__ , KEYALL)
|
||||
KEYWORD(__module_private__ , KEYALL)
|
||||
|
||||
UNARY_EXPR_OR_TYPE_TRAIT(__builtin_ptrauth_type_discriminator, PtrAuthTypeDiscriminator, KEYALL)
|
||||
|
||||
// Extension that will be enabled for Microsoft, Borland and PS4, but can be
|
||||
// disabled via '-fno-declspec'.
|
||||
KEYWORD(__declspec , 0)
|
||||
|
||||
@@ -1165,19 +1165,19 @@ def client__name : JoinedOrSeparate<["-"], "client_name">;
|
||||
def combine : Flag<["-", "--"], "combine">, Flags<[NoXarchOption, Unsupported]>;
|
||||
def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
|
||||
def config : Joined<["--"], "config=">, Flags<[NoXarchOption]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption]>, MetaVarName<"<file>">,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, MetaVarName<"<file>">,
|
||||
HelpText<"Specify configuration file">;
|
||||
def : Separate<["--"], "config">, Alias<config>;
|
||||
def : Separate<["--"], "config">, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, Alias<config>;
|
||||
def no_default_config : Flag<["--"], "no-default-config">,
|
||||
Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption]>,
|
||||
Flags<[NoXarchOption]>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
|
||||
HelpText<"Disable loading default configuration files">;
|
||||
def config_system_dir_EQ : Joined<["--"], "config-system-dir=">,
|
||||
Flags<[NoXarchOption, HelpHidden]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
|
||||
HelpText<"System directory for configuration files">;
|
||||
def config_user_dir_EQ : Joined<["--"], "config-user-dir=">,
|
||||
Flags<[NoXarchOption, HelpHidden]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption]>,
|
||||
Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>,
|
||||
HelpText<"User directory for configuration files">;
|
||||
def coverage : Flag<["-", "--"], "coverage">, Group<Link_Group>,
|
||||
Visibility<[ClangOption, CLOption]>;
|
||||
|
||||
@@ -3890,6 +3890,8 @@ class Parser : public CodeCompletionHandler {
|
||||
ExprResult ParseArrayTypeTrait();
|
||||
ExprResult ParseExpressionTrait();
|
||||
|
||||
ExprResult ParseBuiltinPtrauthTypeDiscriminator();
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Preprocessor code-completion pass-through
|
||||
void CodeCompleteDirective(bool InConditional) override;
|
||||
|
||||
@@ -998,7 +998,9 @@ class Sema;
|
||||
private:
|
||||
friend class OverloadCandidateSet;
|
||||
OverloadCandidate()
|
||||
: IsSurrogate(false), IsADLCandidate(CallExpr::NotADL), RewriteKind(CRK_None) {}
|
||||
: IsSurrogate(false), IgnoreObjectArgument(false),
|
||||
TookAddressOfOverload(false), IsADLCandidate(CallExpr::NotADL),
|
||||
RewriteKind(CRK_None) {}
|
||||
};
|
||||
|
||||
/// OverloadCandidateSet - A set of overload candidates, used in C++
|
||||
|
||||
@@ -3456,6 +3456,8 @@ class Sema final : public SemaBase {
|
||||
TemplateIdAnnotation *TemplateId,
|
||||
bool IsMemberSpecialization);
|
||||
|
||||
bool checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range);
|
||||
|
||||
bool checkConstantPointerAuthKey(Expr *keyExpr, unsigned &key);
|
||||
|
||||
/// Diagnose function specifiers on a declaration of an identifier that
|
||||
|
||||
@@ -2839,6 +2839,8 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
|
||||
// During constant-folding, a negative shift is an opposite shift. Such
|
||||
// a shift is not a constant expression.
|
||||
Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS;
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
RHS = -RHS;
|
||||
goto shift_right;
|
||||
}
|
||||
@@ -2849,19 +2851,23 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
|
||||
if (SA != RHS) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_large_shift)
|
||||
<< RHS << E->getType() << LHS.getBitWidth();
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
} else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus20) {
|
||||
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
|
||||
// operand, and must not overflow the corresponding unsigned type.
|
||||
// C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
|
||||
// E1 x 2^E2 module 2^N.
|
||||
if (LHS.isNegative())
|
||||
if (LHS.isNegative()) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS;
|
||||
else if (LHS.countl_zero() < SA)
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
} else if (LHS.countl_zero() < SA) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_lshift_discards);
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
|
||||
Info.getLangOpts().CPlusPlus11)
|
||||
return false;
|
||||
Result = LHS << SA;
|
||||
return true;
|
||||
}
|
||||
@@ -2875,6 +2881,8 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
|
||||
// During constant-folding, a negative shift is an opposite shift. Such a
|
||||
// shift is not a constant expression.
|
||||
Info.CCEDiag(E, diag::note_constexpr_negative_shift) << RHS;
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
RHS = -RHS;
|
||||
goto shift_left;
|
||||
}
|
||||
@@ -2882,13 +2890,13 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
|
||||
// C++11 [expr.shift]p1: Shift width must be less than the bit width of the
|
||||
// shifted type.
|
||||
unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
|
||||
if (SA != RHS)
|
||||
if (SA != RHS) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_large_shift)
|
||||
<< RHS << E->getType() << LHS.getBitWidth();
|
||||
if (!Info.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
|
||||
Info.getLangOpts().CPlusPlus11)
|
||||
return false;
|
||||
Result = LHS >> SA;
|
||||
return true;
|
||||
}
|
||||
@@ -14054,6 +14062,12 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr(
|
||||
E);
|
||||
}
|
||||
|
||||
case UETT_PtrAuthTypeDiscriminator: {
|
||||
if (E->getArgumentType()->isDependentType())
|
||||
return false;
|
||||
return Success(
|
||||
Info.Ctx.getPointerAuthTypeDiscriminator(E->getArgumentType()), E);
|
||||
}
|
||||
case UETT_VecStep: {
|
||||
QualType Ty = E->getTypeOfArgument();
|
||||
|
||||
|
||||
@@ -153,7 +153,8 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
|
||||
if (RHS.isNegative()) {
|
||||
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
||||
S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
|
||||
return false;
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
|
||||
// C++11 [expr.shift]p1: Shift width must be less than the bit width of
|
||||
@@ -163,17 +164,24 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
|
||||
const APSInt Val = RHS.toAPSInt();
|
||||
QualType Ty = E->getType();
|
||||
S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
|
||||
return !(S.getEvalStatus().Diag && !S.getEvalStatus().Diag->empty() && S.getLangOpts().CPlusPlus11);
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
|
||||
const Expr *E = S.Current->getExpr(OpPC);
|
||||
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
|
||||
// operand, and must not overflow the corresponding unsigned type.
|
||||
if (LHS.isNegative())
|
||||
if (LHS.isNegative()) {
|
||||
S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
|
||||
else if (LHS.toUnsigned().countLeadingZeros() < static_cast<unsigned>(RHS))
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
} else if (LHS.toUnsigned().countLeadingZeros() <
|
||||
static_cast<unsigned>(RHS)) {
|
||||
S.CCEDiag(E, diag::note_constexpr_lshift_discards);
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// C++2a [expr.shift]p2: [P0907R4]:
|
||||
@@ -2269,8 +2277,7 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
|
||||
// shift is not a constant expression.
|
||||
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
||||
S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
|
||||
if (S.getLangOpts().CPlusPlus11 && S.getEvalStatus().Diag &&
|
||||
!S.getEvalStatus().Diag->empty())
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
RHS = -RHS;
|
||||
return DoShift < LT, RT,
|
||||
@@ -2286,8 +2293,7 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
|
||||
// E1 x 2^E2 module 2^N.
|
||||
const SourceInfo &Loc = S.Current->getSource(OpPC);
|
||||
S.CCEDiag(Loc, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
|
||||
if (S.getLangOpts().CPlusPlus11 && S.getEvalStatus().Diag &&
|
||||
!S.getEvalStatus().Diag->empty())
|
||||
if (!S.noteUndefinedBehavior())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5179,6 +5179,14 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
|
||||
Diags.Report(DiagID);
|
||||
return;
|
||||
}
|
||||
case UETT_PtrAuthTypeDiscriminator: {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"cannot yet mangle __builtin_ptrauth_type_discriminator expression");
|
||||
Diags.Report(E->getExprLoc(), DiagID);
|
||||
return;
|
||||
}
|
||||
case UETT_VecStep: {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
|
||||
@@ -385,6 +385,8 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
|
||||
Builder.defineMacro("_ARCH_PWR9");
|
||||
if (ArchDefs & ArchDefinePwr10)
|
||||
Builder.defineMacro("_ARCH_PWR10");
|
||||
if (ArchDefs & ArchDefinePwr11)
|
||||
Builder.defineMacro("_ARCH_PWR11");
|
||||
if (ArchDefs & ArchDefineA2)
|
||||
Builder.defineMacro("_ARCH_A2");
|
||||
if (ArchDefs & ArchDefineE500)
|
||||
@@ -622,10 +624,17 @@ bool PPCTargetInfo::initFeatureMap(
|
||||
addP10SpecificFeatures(Features);
|
||||
}
|
||||
|
||||
// Future CPU should include all of the features of Power 10 as well as any
|
||||
// Power11 includes all the same features as Power10 plus any features
|
||||
// specific to the Power11 core.
|
||||
if (CPU == "pwr11" || CPU == "power11") {
|
||||
initFeatureMap(Features, Diags, "pwr10", FeaturesVec);
|
||||
addP11SpecificFeatures(Features);
|
||||
}
|
||||
|
||||
// Future CPU should include all of the features of Power 11 as well as any
|
||||
// additional features (yet to be determined) specific to it.
|
||||
if (CPU == "future") {
|
||||
initFeatureMap(Features, Diags, "pwr10", FeaturesVec);
|
||||
initFeatureMap(Features, Diags, "pwr11", FeaturesVec);
|
||||
addFutureSpecificFeatures(Features);
|
||||
}
|
||||
|
||||
@@ -696,6 +705,10 @@ void PPCTargetInfo::addP10SpecificFeatures(
|
||||
Features["isa-v31-instructions"] = true;
|
||||
}
|
||||
|
||||
// Add any Power11 specific features.
|
||||
void PPCTargetInfo::addP11SpecificFeatures(
|
||||
llvm::StringMap<bool> &Features) const {}
|
||||
|
||||
// Add features specific to the "Future" CPU.
|
||||
void PPCTargetInfo::addFutureSpecificFeatures(
|
||||
llvm::StringMap<bool> &Features) const {}
|
||||
@@ -870,17 +883,17 @@ ArrayRef<TargetInfo::AddlRegName> PPCTargetInfo::getGCCAddlRegNames() const {
|
||||
}
|
||||
|
||||
static constexpr llvm::StringLiteral ValidCPUNames[] = {
|
||||
{"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
|
||||
{"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
|
||||
{"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
|
||||
{"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"},
|
||||
{"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"},
|
||||
{"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"},
|
||||
{"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"},
|
||||
{"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"},
|
||||
{"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"},
|
||||
{"powerpc"}, {"ppc"}, {"ppc32"}, {"powerpc64"}, {"ppc64"},
|
||||
{"powerpc64le"}, {"ppc64le"}, {"future"}};
|
||||
{"generic"}, {"440"}, {"450"}, {"601"}, {"602"},
|
||||
{"603"}, {"603e"}, {"603ev"}, {"604"}, {"604e"},
|
||||
{"620"}, {"630"}, {"g3"}, {"7400"}, {"g4"},
|
||||
{"7450"}, {"g4+"}, {"750"}, {"8548"}, {"970"},
|
||||
{"g5"}, {"a2"}, {"e500"}, {"e500mc"}, {"e5500"},
|
||||
{"power3"}, {"pwr3"}, {"power4"}, {"pwr4"}, {"power5"},
|
||||
{"pwr5"}, {"power5x"}, {"pwr5x"}, {"power6"}, {"pwr6"},
|
||||
{"power6x"}, {"pwr6x"}, {"power7"}, {"pwr7"}, {"power8"},
|
||||
{"pwr8"}, {"power9"}, {"pwr9"}, {"power10"}, {"pwr10"},
|
||||
{"power11"}, {"pwr11"}, {"powerpc"}, {"ppc"}, {"ppc32"},
|
||||
{"powerpc64"}, {"ppc64"}, {"powerpc64le"}, {"ppc64le"}, {"future"}};
|
||||
|
||||
bool PPCTargetInfo::isValidCPUName(StringRef Name) const {
|
||||
return llvm::is_contained(ValidCPUNames, Name);
|
||||
|
||||
@@ -44,8 +44,9 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
|
||||
ArchDefinePwr8 = 1 << 12,
|
||||
ArchDefinePwr9 = 1 << 13,
|
||||
ArchDefinePwr10 = 1 << 14,
|
||||
ArchDefineFuture = 1 << 15,
|
||||
ArchDefineA2 = 1 << 16,
|
||||
ArchDefinePwr11 = 1 << 15,
|
||||
ArchDefineFuture = 1 << 16,
|
||||
ArchDefineA2 = 1 << 17,
|
||||
ArchDefineE500 = 1 << 18
|
||||
} ArchDefineTypes;
|
||||
|
||||
@@ -166,11 +167,16 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
|
||||
ArchDefinePwr7 | ArchDefinePwr6 | ArchDefinePwr5x |
|
||||
ArchDefinePwr5 | ArchDefinePwr4 | ArchDefinePpcgr |
|
||||
ArchDefinePpcsq)
|
||||
.Cases("power11", "pwr11",
|
||||
ArchDefinePwr11 | ArchDefinePwr10 | ArchDefinePwr9 |
|
||||
ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 |
|
||||
ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
|
||||
ArchDefinePpcgr | ArchDefinePpcsq)
|
||||
.Case("future",
|
||||
ArchDefineFuture | ArchDefinePwr10 | ArchDefinePwr9 |
|
||||
ArchDefinePwr8 | ArchDefinePwr7 | ArchDefinePwr6 |
|
||||
ArchDefinePwr5x | ArchDefinePwr5 | ArchDefinePwr4 |
|
||||
ArchDefinePpcgr | ArchDefinePpcsq)
|
||||
ArchDefineFuture | ArchDefinePwr11 | ArchDefinePwr10 |
|
||||
ArchDefinePwr9 | ArchDefinePwr8 | ArchDefinePwr7 |
|
||||
ArchDefinePwr6 | ArchDefinePwr5x | ArchDefinePwr5 |
|
||||
ArchDefinePwr4 | ArchDefinePpcgr | ArchDefinePpcsq)
|
||||
.Cases("8548", "e500", ArchDefineE500)
|
||||
.Default(ArchDefineNone);
|
||||
}
|
||||
@@ -192,6 +198,7 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
|
||||
const std::vector<std::string> &FeaturesVec) const override;
|
||||
|
||||
void addP10SpecificFeatures(llvm::StringMap<bool> &Features) const;
|
||||
void addP11SpecificFeatures(llvm::StringMap<bool> &Features) const;
|
||||
void addFutureSpecificFeatures(llvm::StringMap<bool> &Features) const;
|
||||
|
||||
bool handleTargetFeatures(std::vector<std::string> &Features,
|
||||
|
||||
@@ -1695,7 +1695,8 @@ void CGOpenMPRuntimeGPU::emitReduction(
|
||||
CGF.AllocaInsertPt->getIterator());
|
||||
InsertPointTy CodeGenIP(CGF.Builder.GetInsertBlock(),
|
||||
CGF.Builder.GetInsertPoint());
|
||||
llvm::OpenMPIRBuilder::LocationDescription OmpLoc(CodeGenIP);
|
||||
llvm::OpenMPIRBuilder::LocationDescription OmpLoc(
|
||||
CodeGenIP, CGF.SourceLocToDebugLoc(Loc));
|
||||
llvm::SmallVector<llvm::OpenMPIRBuilder::ReductionInfo> ReductionInfos;
|
||||
|
||||
CodeGenFunction::OMPPrivateScope Scope(CGF);
|
||||
|
||||
@@ -70,6 +70,7 @@ static std::string normalizeCPUName(StringRef CPUName, const llvm::Triple &T) {
|
||||
.Case("power8", "pwr8")
|
||||
.Case("power9", "pwr9")
|
||||
.Case("power10", "pwr10")
|
||||
.Case("power11", "pwr11")
|
||||
.Case("future", "future")
|
||||
.Case("powerpc", "ppc")
|
||||
.Case("powerpc64", "ppc64")
|
||||
@@ -103,6 +104,8 @@ const char *ppc::getPPCAsmModeForCPU(StringRef Name) {
|
||||
.Case("power9", "-mpower9")
|
||||
.Case("pwr10", "-mpower10")
|
||||
.Case("power10", "-mpower10")
|
||||
.Case("pwr11", "-mpower11")
|
||||
.Case("power11", "-mpower11")
|
||||
.Default("-many");
|
||||
}
|
||||
|
||||
|
||||
@@ -1516,6 +1516,10 @@ static void handlePAuthABI(const ArgList &DriverArgs, ArgStringList &CC1Args) {
|
||||
options::OPT_fno_ptrauth_vtable_pointer_type_discrimination))
|
||||
CC1Args.push_back("-fptrauth-vtable-pointer-type-discrimination");
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_indirect_gotos,
|
||||
options::OPT_fno_ptrauth_indirect_gotos))
|
||||
CC1Args.push_back("-fptrauth-indirect-gotos");
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_fptrauth_init_fini,
|
||||
options::OPT_fno_ptrauth_init_fini))
|
||||
CC1Args.push_back("-fptrauth-init-fini");
|
||||
|
||||
@@ -202,6 +202,23 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
|
||||
#define ptrauth_string_discriminator(__string) \
|
||||
__builtin_ptrauth_string_discriminator(__string)
|
||||
|
||||
/* Compute a constant discriminator from the given type.
|
||||
|
||||
The result can be used as the second argument to
|
||||
ptrauth_blend_discriminator or the third argument to the
|
||||
__ptrauth qualifier. It has type size_t.
|
||||
|
||||
If the type is a C++ member function pointer type, the result is
|
||||
the discriminator used to signed member function pointers of that
|
||||
type. If the type is a function, function pointer, or function
|
||||
reference type, the result is the discriminator used to sign
|
||||
functions of that type. It is ill-formed to use this macro with any
|
||||
other type.
|
||||
|
||||
A call to this function is an integer constant expression. */
|
||||
#define ptrauth_type_discriminator(__type) \
|
||||
__builtin_ptrauth_type_discriminator(__type)
|
||||
|
||||
/* Compute a signature for the given pair of pointer-sized values.
|
||||
The order of the arguments is significant.
|
||||
|
||||
@@ -289,6 +306,8 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
|
||||
((ptrauth_extra_data_t)0); \
|
||||
})
|
||||
|
||||
#define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0)
|
||||
|
||||
#define ptrauth_sign_generic_data(__value, __data) \
|
||||
({ \
|
||||
(void)__value; \
|
||||
|
||||
@@ -20,19 +20,18 @@
|
||||
* modules.
|
||||
*/
|
||||
#if defined(__MVS__) && __has_include_next(<stdarg.h>)
|
||||
#include <__stdarg_header_macro.h>
|
||||
#undef __need___va_list
|
||||
#undef __need_va_list
|
||||
#undef __need_va_arg
|
||||
#undef __need___va_copy
|
||||
#undef __need_va_copy
|
||||
#include <__stdarg_header_macro.h>
|
||||
#include_next <stdarg.h>
|
||||
|
||||
#else
|
||||
#if !defined(__need___va_list) && !defined(__need_va_list) && \
|
||||
!defined(__need_va_arg) && !defined(__need___va_copy) && \
|
||||
!defined(__need_va_copy)
|
||||
#include <__stdarg_header_macro.h>
|
||||
#define __need___va_list
|
||||
#define __need_va_list
|
||||
#define __need_va_arg
|
||||
@@ -45,6 +44,7 @@
|
||||
!defined(__STRICT_ANSI__)
|
||||
#define __need_va_copy
|
||||
#endif
|
||||
#include <__stdarg_header_macro.h>
|
||||
#endif
|
||||
|
||||
#ifdef __need___va_list
|
||||
|
||||
@@ -172,7 +172,11 @@ typedef _Atomic(uintmax_t) atomic_uintmax_t;
|
||||
|
||||
typedef struct atomic_flag { atomic_bool _Value; } atomic_flag;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define ATOMIC_FLAG_INIT {false}
|
||||
#else
|
||||
#define ATOMIC_FLAG_INIT { 0 }
|
||||
#endif
|
||||
|
||||
/* These should be provided by the libc implementation. */
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
* modules.
|
||||
*/
|
||||
#if defined(__MVS__) && __has_include_next(<stddef.h>)
|
||||
#include <__stddef_header_macro.h>
|
||||
#undef __need_ptrdiff_t
|
||||
#undef __need_size_t
|
||||
#undef __need_rsize_t
|
||||
@@ -31,6 +30,7 @@
|
||||
#undef __need_max_align_t
|
||||
#undef __need_offsetof
|
||||
#undef __need_wint_t
|
||||
#include <__stddef_header_macro.h>
|
||||
#include_next <stddef.h>
|
||||
|
||||
#else
|
||||
@@ -40,7 +40,6 @@
|
||||
!defined(__need_NULL) && !defined(__need_nullptr_t) && \
|
||||
!defined(__need_unreachable) && !defined(__need_max_align_t) && \
|
||||
!defined(__need_offsetof) && !defined(__need_wint_t)
|
||||
#include <__stddef_header_macro.h>
|
||||
#define __need_ptrdiff_t
|
||||
#define __need_size_t
|
||||
/* ISO9899:2011 7.20 (C11 Annex K): Define rsize_t if __STDC_WANT_LIB_EXT1__ is
|
||||
@@ -49,7 +48,24 @@
|
||||
#define __need_rsize_t
|
||||
#endif
|
||||
#define __need_wchar_t
|
||||
#if !defined(__STDDEF_H) || __has_feature(modules)
|
||||
/*
|
||||
* __stddef_null.h is special when building without modules: if __need_NULL is
|
||||
* set, then it will unconditionally redefine NULL. To avoid stepping on client
|
||||
* definitions of NULL, __need_NULL should only be set the first time this
|
||||
* header is included, that is when __STDDEF_H is not defined. However, when
|
||||
* building with modules, this header is a textual header and needs to
|
||||
* unconditionally include __stdef_null.h to support multiple submodules
|
||||
* exporting _Builtin_stddef.null. Take module SM with submodules A and B, whose
|
||||
* headers both include stddef.h When SM.A builds, __STDDEF_H will be defined.
|
||||
* When SM.B builds, the definition from SM.A will leak when building without
|
||||
* local submodule visibility. stddef.h wouldn't include __stddef_null.h, and
|
||||
* SM.B wouldn't import _Builtin_stddef.null, and SM.B's `export *` wouldn't
|
||||
* export NULL as expected. When building with modules, always include
|
||||
* __stddef_null.h so that everything works as expected.
|
||||
*/
|
||||
#define __need_NULL
|
||||
#endif
|
||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || \
|
||||
defined(__cplusplus)
|
||||
#define __need_nullptr_t
|
||||
@@ -65,6 +81,7 @@
|
||||
/* wint_t is provided by <wchar.h> and not <stddef.h>. It's here
|
||||
* for compatibility, but must be explicitly requested. Therefore
|
||||
* __need_wint_t is intentionally not defined here. */
|
||||
#include <__stddef_header_macro.h>
|
||||
#endif
|
||||
|
||||
#if defined(__need_ptrdiff_t)
|
||||
|
||||
@@ -763,6 +763,9 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback {
|
||||
bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,
|
||||
tok::TokenKind *Kind) {
|
||||
if (RevertibleTypeTraits.empty()) {
|
||||
// Revertible type trait is a feature for backwards compatibility with older
|
||||
// standard libraries that declare their own structs with the same name as
|
||||
// the builtins listed below. New builtins should NOT be added to this list.
|
||||
#define RTT_JOIN(X, Y) X##Y
|
||||
#define REVERTIBLE_TYPE_TRAIT(Name) \
|
||||
RevertibleTypeTraits[PP.getIdentifierInfo(#Name)] = RTT_JOIN(tok::kw_, Name)
|
||||
@@ -790,7 +793,6 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,
|
||||
REVERTIBLE_TYPE_TRAIT(__is_fundamental);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_integral);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_interface_class);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_layout_compatible);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_literal);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_lvalue_expr);
|
||||
REVERTIBLE_TYPE_TRAIT(__is_lvalue_reference);
|
||||
@@ -841,6 +843,26 @@ bool Parser::isRevertibleTypeTrait(const IdentifierInfo *II,
|
||||
return false;
|
||||
}
|
||||
|
||||
ExprResult Parser::ParseBuiltinPtrauthTypeDiscriminator() {
|
||||
SourceLocation Loc = ConsumeToken();
|
||||
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
if (T.expectAndConsume())
|
||||
return ExprError();
|
||||
|
||||
TypeResult Ty = ParseTypeName();
|
||||
if (Ty.isInvalid()) {
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
SourceLocation EndLoc = Tok.getLocation();
|
||||
T.consumeClose();
|
||||
return Actions.ActOnUnaryExprOrTypeTraitExpr(
|
||||
Loc, UETT_PtrAuthTypeDiscriminator,
|
||||
/*isType=*/true, Ty.get().getAsOpaquePtr(), SourceRange(Loc, EndLoc));
|
||||
}
|
||||
|
||||
/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse
|
||||
/// a unary-expression.
|
||||
///
|
||||
@@ -1806,6 +1828,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
|
||||
Res = ParseArrayTypeTrait();
|
||||
break;
|
||||
|
||||
case tok::kw___builtin_ptrauth_type_discriminator:
|
||||
return ParseBuiltinPtrauthTypeDiscriminator();
|
||||
|
||||
case tok::kw___is_lvalue_expr:
|
||||
case tok::kw___is_rvalue_expr:
|
||||
if (NotPrimaryExpression)
|
||||
|
||||
@@ -1489,14 +1489,18 @@ enum PointerAuthOpKind {
|
||||
};
|
||||
}
|
||||
|
||||
static bool checkPointerAuthEnabled(Sema &S, Expr *E) {
|
||||
if (S.getLangOpts().PointerAuthIntrinsics)
|
||||
bool Sema::checkPointerAuthEnabled(SourceLocation Loc, SourceRange Range) {
|
||||
if (getLangOpts().PointerAuthIntrinsics)
|
||||
return false;
|
||||
|
||||
S.Diag(E->getExprLoc(), diag::err_ptrauth_disabled) << E->getSourceRange();
|
||||
Diag(Loc, diag::err_ptrauth_disabled) << Range;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool checkPointerAuthEnabled(Sema &S, Expr *E) {
|
||||
return S.checkPointerAuthEnabled(E->getExprLoc(), E->getSourceRange());
|
||||
}
|
||||
|
||||
static bool checkPointerAuthKey(Sema &S, Expr *&Arg) {
|
||||
// Convert it to type 'int'.
|
||||
if (convertArgumentToType(S, Arg, S.Context.IntTy))
|
||||
|
||||
@@ -4117,6 +4117,21 @@ static bool CheckVectorElementsTraitOperandType(Sema &S, QualType T,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkPtrAuthTypeDiscriminatorOperandType(Sema &S, QualType T,
|
||||
SourceLocation Loc,
|
||||
SourceRange ArgRange) {
|
||||
if (S.checkPointerAuthEnabled(Loc, ArgRange))
|
||||
return true;
|
||||
|
||||
if (!T->isFunctionType() && !T->isFunctionPointerType() &&
|
||||
!T->isFunctionReferenceType() && !T->isMemberFunctionPointerType()) {
|
||||
S.Diag(Loc, diag::err_ptrauth_type_disc_undiscriminated) << T << ArgRange;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CheckExtensionTraitOperandType(Sema &S, QualType T,
|
||||
SourceLocation Loc,
|
||||
SourceRange ArgRange,
|
||||
@@ -4511,6 +4526,10 @@ bool Sema::CheckUnaryExprOrTypeTraitOperand(QualType ExprType,
|
||||
return CheckVectorElementsTraitOperandType(*this, ExprType, OpLoc,
|
||||
ExprRange);
|
||||
|
||||
if (ExprKind == UETT_PtrAuthTypeDiscriminator)
|
||||
return checkPtrAuthTypeDiscriminatorOperandType(*this, ExprType, OpLoc,
|
||||
ExprRange);
|
||||
|
||||
// Explicitly list some types as extensions.
|
||||
if (!CheckExtensionTraitOperandType(*this, ExprType, OpLoc, ExprRange,
|
||||
ExprKind))
|
||||
@@ -5711,7 +5730,6 @@ static bool isParenthetizedAndQualifiedAddressOfExpr(Expr *Fn) {
|
||||
if (!UO || UO->getOpcode() != clang::UO_AddrOf)
|
||||
return false;
|
||||
if (auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr()->IgnoreParens())) {
|
||||
assert(isa<FunctionDecl>(DRE->getDecl()) && "expected a function");
|
||||
return DRE->hasQualifier();
|
||||
}
|
||||
if (auto *OVL = dyn_cast<OverloadExpr>(UO->getSubExpr()->IgnoreParens()))
|
||||
@@ -17027,7 +17045,8 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
|
||||
// not a constant expression as a side-effect.
|
||||
bool Folded =
|
||||
E->EvaluateAsRValue(EvalResult, Context, /*isConstantContext*/ true) &&
|
||||
EvalResult.Val.isInt() && !EvalResult.HasSideEffects;
|
||||
EvalResult.Val.isInt() && !EvalResult.HasSideEffects &&
|
||||
(!getLangOpts().CPlusPlus || !EvalResult.HasUndefinedBehavior);
|
||||
|
||||
if (!isa<ConstantExpr>(E))
|
||||
E = ConstantExpr::Create(Context, E, EvalResult.Val);
|
||||
|
||||
@@ -6857,10 +6857,7 @@ void Sema::AddOverloadCandidate(
|
||||
Candidate.Viable = true;
|
||||
Candidate.RewriteKind =
|
||||
CandidateSet.getRewriteInfo().getRewriteKind(Function, PO);
|
||||
Candidate.IsSurrogate = false;
|
||||
Candidate.IsADLCandidate = IsADLCandidate;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.ExplicitCallArguments = Args.size();
|
||||
|
||||
// Explicit functions are not actually candidates at all if we're not
|
||||
@@ -7422,8 +7419,6 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, DeclAccessPair FoundDecl,
|
||||
Candidate.Function = Method;
|
||||
Candidate.RewriteKind =
|
||||
CandidateSet.getRewriteInfo().getRewriteKind(Method, PO);
|
||||
Candidate.IsSurrogate = false;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload =
|
||||
CandidateSet.getKind() == OverloadCandidateSet::CSK_AddressOfOverloadSet;
|
||||
Candidate.ExplicitCallArguments = Args.size();
|
||||
@@ -7617,7 +7612,6 @@ void Sema::AddMethodTemplateCandidate(
|
||||
Candidate.IgnoreObjectArgument =
|
||||
cast<CXXMethodDecl>(Candidate.Function)->isStatic() ||
|
||||
ObjectType.isNull();
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.ExplicitCallArguments = Args.size();
|
||||
if (Result == TemplateDeductionResult::NonDependentConversionFailure)
|
||||
Candidate.FailureKind = ovl_fail_bad_conversion;
|
||||
@@ -7705,7 +7699,6 @@ void Sema::AddTemplateOverloadCandidate(
|
||||
Candidate.IgnoreObjectArgument =
|
||||
isa<CXXMethodDecl>(Candidate.Function) &&
|
||||
!isa<CXXConstructorDecl>(Candidate.Function);
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.ExplicitCallArguments = Args.size();
|
||||
if (Result == TemplateDeductionResult::NonDependentConversionFailure)
|
||||
Candidate.FailureKind = ovl_fail_bad_conversion;
|
||||
@@ -7886,9 +7879,6 @@ void Sema::AddConversionCandidate(
|
||||
OverloadCandidate &Candidate = CandidateSet.addCandidate(1);
|
||||
Candidate.FoundDecl = FoundDecl;
|
||||
Candidate.Function = Conversion;
|
||||
Candidate.IsSurrogate = false;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.FinalConversion.setAsIdentityConversion();
|
||||
Candidate.FinalConversion.setFromType(ConvType);
|
||||
Candidate.FinalConversion.setAllToTypes(ToType);
|
||||
@@ -8084,9 +8074,6 @@ void Sema::AddTemplateConversionCandidate(
|
||||
Candidate.Function = FunctionTemplate->getTemplatedDecl();
|
||||
Candidate.Viable = false;
|
||||
Candidate.FailureKind = ovl_fail_bad_deduction;
|
||||
Candidate.IsSurrogate = false;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.ExplicitCallArguments = 1;
|
||||
Candidate.DeductionFailure = MakeDeductionFailureInfo(Context, Result,
|
||||
Info);
|
||||
@@ -8119,10 +8106,8 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
|
||||
Candidate.FoundDecl = FoundDecl;
|
||||
Candidate.Function = nullptr;
|
||||
Candidate.Surrogate = Conversion;
|
||||
Candidate.Viable = true;
|
||||
Candidate.IsSurrogate = true;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
Candidate.Viable = true;
|
||||
Candidate.ExplicitCallArguments = Args.size();
|
||||
|
||||
// Determine the implicit conversion sequence for the implicit
|
||||
@@ -8328,9 +8313,6 @@ void Sema::AddBuiltinCandidate(QualType *ParamTys, ArrayRef<Expr *> Args,
|
||||
OverloadCandidate &Candidate = CandidateSet.addCandidate(Args.size());
|
||||
Candidate.FoundDecl = DeclAccessPair::make(nullptr, AS_none);
|
||||
Candidate.Function = nullptr;
|
||||
Candidate.IsSurrogate = false;
|
||||
Candidate.IgnoreObjectArgument = false;
|
||||
Candidate.TookAddressOfOverload = false;
|
||||
std::copy(ParamTys, ParamTys + Args.size(), Candidate.BuiltinParamTypes);
|
||||
|
||||
// Determine the implicit conversion sequences for each of the
|
||||
|
||||
@@ -272,6 +272,11 @@ switch32
|
||||
switch8
|
||||
switchu8
|
||||
|
||||
// This function generates a custom trampoline function with the specific
|
||||
// realFunc and localsPtr values.
|
||||
void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
|
||||
const void* realFunc, void* localsPtr);
|
||||
|
||||
// There is no C interface to the *_vfp_d8_d15_regs functions. There are
|
||||
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
|
||||
// SJLJ for exceptions, each function with a catch clause or destructors needs
|
||||
|
||||
@@ -10,15 +10,6 @@ struct FEATURES {
|
||||
|
||||
extern struct FEATURES __aarch64_cpu_features;
|
||||
|
||||
struct SME_STATE {
|
||||
long PSTATE;
|
||||
long TPIDR2_EL0;
|
||||
};
|
||||
|
||||
extern struct SME_STATE __arm_sme_state(void) __arm_streaming_compatible;
|
||||
|
||||
extern bool __aarch64_has_sme_and_tpidr2_el0;
|
||||
|
||||
#if __GNUC__ >= 9
|
||||
#pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
|
||||
#endif
|
||||
@@ -28,22 +19,3 @@ __attribute__((constructor(90))) static void get_aarch64_cpu_features(void) {
|
||||
|
||||
__init_cpu_features();
|
||||
}
|
||||
|
||||
__attribute__((target("sve"))) long
|
||||
__arm_get_current_vg(void) __arm_streaming_compatible {
|
||||
struct SME_STATE State = __arm_sme_state();
|
||||
unsigned long long features =
|
||||
__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED);
|
||||
bool HasSVE = features & (1ULL << FEAT_SVE);
|
||||
|
||||
if (!HasSVE && !__aarch64_has_sme_and_tpidr2_el0)
|
||||
return 0;
|
||||
|
||||
if (HasSVE || (State.PSTATE & 1)) {
|
||||
long vl;
|
||||
__asm__ __volatile__("cntd %0" : "=r"(vl));
|
||||
return vl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12,11 +12,15 @@
|
||||
#if !defined(__APPLE__)
|
||||
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
|
||||
#define TPIDR2_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
|
||||
#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)
|
||||
#define CPU_FEATS_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_cpu_features)
|
||||
#else
|
||||
// MachO requires @page/@pageoff directives because the global is defined
|
||||
// in a different file. Otherwise this file may fail to build.
|
||||
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@page
|
||||
#define TPIDR2_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@pageoff
|
||||
#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)@page
|
||||
#define CPU_FEATS_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_cpu_features)@pageoff
|
||||
#endif
|
||||
|
||||
.arch armv9-a+sme
|
||||
@@ -180,6 +184,46 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable)
|
||||
ret
|
||||
END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable)
|
||||
|
||||
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_get_current_vg)
|
||||
.variant_pcs __arm_get_current_vg
|
||||
BTI_C
|
||||
|
||||
stp x29, x30, [sp, #-16]!
|
||||
.cfi_def_cfa_offset 16
|
||||
mov x29, sp
|
||||
.cfi_def_cfa w29, 16
|
||||
.cfi_offset w30, -8
|
||||
.cfi_offset w29, -16
|
||||
adrp x17, CPU_FEATS_SYMBOL
|
||||
ldr w17, [x17, CPU_FEATS_SYMBOL_OFFSET]
|
||||
tbnz w17, #30, 0f
|
||||
adrp x16, TPIDR2_SYMBOL
|
||||
ldrb w16, [x16, TPIDR2_SYMBOL_OFFSET]
|
||||
cbz w16, 1f
|
||||
0:
|
||||
mov x18, x1
|
||||
bl __arm_sme_state
|
||||
mov x1, x18
|
||||
and x17, x17, #0x40000000
|
||||
bfxil x17, x0, #0, #1
|
||||
cbz x17, 1f
|
||||
cntd x0
|
||||
.cfi_def_cfa wsp, 16
|
||||
ldp x29, x30, [sp], #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore w30
|
||||
.cfi_restore w29
|
||||
ret
|
||||
1:
|
||||
mov x0, xzr
|
||||
.cfi_def_cfa wsp, 16
|
||||
ldp x29, x30, [sp], #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore w30
|
||||
.cfi_restore w29
|
||||
ret
|
||||
END_COMPILERRT_OUTLINE_FUNCTION(__arm_get_current_vg)
|
||||
|
||||
NO_EXEC_STACK_DIRECTIVE
|
||||
|
||||
// GNU property note for BTI and PAC
|
||||
|
||||
@@ -41,3 +41,45 @@ COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
|
||||
__clear_cache(trampOnStack, &trampOnStack[10]);
|
||||
}
|
||||
#endif // __powerpc__ && !defined(__powerpc64__)
|
||||
|
||||
// The AArch64 compiler generates calls to __trampoline_setup() when creating
|
||||
// trampoline functions on the stack for use with nested functions.
|
||||
// This function creates a custom 36-byte trampoline function on the stack
|
||||
// which loads x18 with a pointer to the outer function's locals
|
||||
// and then jumps to the target nested function.
|
||||
// Note: x18 is a reserved platform register on Windows and macOS.
|
||||
|
||||
#if defined(__aarch64__) && defined(__ELF__)
|
||||
COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
|
||||
int trampSizeAllocated,
|
||||
const void *realFunc, void *localsPtr) {
|
||||
// This should never happen, but if compiler did not allocate
|
||||
// enough space on stack for the trampoline, abort.
|
||||
if (trampSizeAllocated < 36)
|
||||
compilerrt_abort();
|
||||
|
||||
// create trampoline
|
||||
// Load realFunc into x17. mov/movk 16 bits at a time.
|
||||
trampOnStack[0] =
|
||||
0xd2800000u | ((((uint64_t)realFunc >> 0) & 0xffffu) << 5) | 0x11;
|
||||
trampOnStack[1] =
|
||||
0xf2a00000u | ((((uint64_t)realFunc >> 16) & 0xffffu) << 5) | 0x11;
|
||||
trampOnStack[2] =
|
||||
0xf2c00000u | ((((uint64_t)realFunc >> 32) & 0xffffu) << 5) | 0x11;
|
||||
trampOnStack[3] =
|
||||
0xf2e00000u | ((((uint64_t)realFunc >> 48) & 0xffffu) << 5) | 0x11;
|
||||
// Load localsPtr into x18
|
||||
trampOnStack[4] =
|
||||
0xd2800000u | ((((uint64_t)localsPtr >> 0) & 0xffffu) << 5) | 0x12;
|
||||
trampOnStack[5] =
|
||||
0xf2a00000u | ((((uint64_t)localsPtr >> 16) & 0xffffu) << 5) | 0x12;
|
||||
trampOnStack[6] =
|
||||
0xf2c00000u | ((((uint64_t)localsPtr >> 32) & 0xffffu) << 5) | 0x12;
|
||||
trampOnStack[7] =
|
||||
0xf2e00000u | ((((uint64_t)localsPtr >> 48) & 0xffffu) << 5) | 0x12;
|
||||
trampOnStack[8] = 0xd61f0220; // br x17
|
||||
|
||||
// Clear instruction cache.
|
||||
__clear_cache(trampOnStack, &trampOnStack[9]);
|
||||
}
|
||||
#endif // defined(__aarch64__) && !defined(__APPLE__) && !defined(_WIN64)
|
||||
|
||||
@@ -9,31 +9,33 @@
|
||||
#ifndef SANITIZER_PTRAUTH_H
|
||||
#define SANITIZER_PTRAUTH_H
|
||||
|
||||
#if __has_feature(ptrauth_calls)
|
||||
#include <ptrauth.h>
|
||||
#if __has_feature(ptrauth_intrinsics)
|
||||
# include <ptrauth.h>
|
||||
#elif defined(__ARM_FEATURE_PAC_DEFAULT) && !defined(__APPLE__)
|
||||
inline unsigned long ptrauth_strip(void* __value, unsigned int __key) {
|
||||
// On the stack the link register is protected with Pointer
|
||||
// Authentication Code when compiled with -mbranch-protection.
|
||||
// Let's stripping the PAC unconditionally because xpaclri is in
|
||||
// the NOP space so will do nothing when it is not enabled or not available.
|
||||
unsigned long ret;
|
||||
asm volatile(
|
||||
"mov x30, %1\n\t"
|
||||
"hint #7\n\t" // xpaclri
|
||||
"mov %0, x30\n\t"
|
||||
: "=r"(ret)
|
||||
: "r"(__value)
|
||||
: "x30");
|
||||
return ret;
|
||||
}
|
||||
#define ptrauth_auth_data(__value, __old_key, __old_data) __value
|
||||
#define ptrauth_string_discriminator(__string) ((int)0)
|
||||
// On the stack the link register is protected with Pointer
|
||||
// Authentication Code when compiled with -mbranch-protection.
|
||||
// Let's stripping the PAC unconditionally because xpaclri is in
|
||||
// the NOP space so will do nothing when it is not enabled or not available.
|
||||
# define ptrauth_strip(__value, __key) \
|
||||
({ \
|
||||
__typeof(__value) ret; \
|
||||
asm volatile( \
|
||||
"mov x30, %1\n\t" \
|
||||
"hint #7\n\t" \
|
||||
"mov %0, x30\n\t" \
|
||||
"mov x30, xzr\n\t" \
|
||||
: "=r"(ret) \
|
||||
: "r"(__value) \
|
||||
: "x30"); \
|
||||
ret; \
|
||||
})
|
||||
# define ptrauth_auth_data(__value, __old_key, __old_data) __value
|
||||
# define ptrauth_string_discriminator(__string) ((int)0)
|
||||
#else
|
||||
// Copied from <ptrauth.h>
|
||||
#define ptrauth_strip(__value, __key) __value
|
||||
#define ptrauth_auth_data(__value, __old_key, __old_data) __value
|
||||
#define ptrauth_string_discriminator(__string) ((int)0)
|
||||
# define ptrauth_strip(__value, __key) __value
|
||||
# define ptrauth_auth_data(__value, __old_key, __old_data) __value
|
||||
# define ptrauth_string_discriminator(__string) ((int)0)
|
||||
#endif
|
||||
|
||||
#define STRIP_PAC_PC(pc) ((uptr)ptrauth_strip(pc, 0))
|
||||
|
||||
@@ -207,7 +207,7 @@ struct VtablePrefix {
|
||||
std::type_info *TypeInfo;
|
||||
};
|
||||
VtablePrefix *getVtablePrefix(void *Vtable) {
|
||||
Vtable = ptrauth_auth_data(Vtable, ptrauth_key_cxx_vtable_pointer, 0);
|
||||
Vtable = ptrauth_strip(Vtable, ptrauth_key_cxx_vtable_pointer);
|
||||
VtablePrefix *Vptr = reinterpret_cast<VtablePrefix*>(Vtable);
|
||||
VtablePrefix *Prefix = Vptr - 1;
|
||||
if (!IsAccessibleMemoryRange((uptr)Prefix, sizeof(VtablePrefix)))
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <__bit/countr.h>
|
||||
#include <__bit/invert_if.h>
|
||||
#include <__bit/popcount.h>
|
||||
#include <__compare/ordering.h>
|
||||
#include <__config>
|
||||
#include <__fwd/bit_reference.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
@@ -913,6 +914,7 @@ public:
|
||||
return __x.__seg_ == __y.__seg_ && __x.__ctz_ == __y.__ctz_;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER <= 17
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 friend bool
|
||||
operator!=(const __bit_iterator& __x, const __bit_iterator& __y) {
|
||||
return !(__x == __y);
|
||||
@@ -937,6 +939,18 @@ public:
|
||||
operator>=(const __bit_iterator& __x, const __bit_iterator& __y) {
|
||||
return !(__x < __y);
|
||||
}
|
||||
#else // _LIBCPP_STD_VER <= 17
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
|
||||
operator<=>(const __bit_iterator& __x, const __bit_iterator& __y) {
|
||||
if (__x.__seg_ < __y.__seg_)
|
||||
return strong_ordering::less;
|
||||
|
||||
if (__x.__seg_ == __y.__seg_)
|
||||
return __x.__ctz_ <=> __y.__ctz_;
|
||||
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER <= 17
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// _LIBCPP_VERSION represents the version of libc++, which matches the version of LLVM.
|
||||
// Given a LLVM release LLVM XX.YY.ZZ (e.g. LLVM 17.0.1 == 17.00.01), _LIBCPP_VERSION is
|
||||
// defined to XXYYZZ.
|
||||
# define _LIBCPP_VERSION 190000
|
||||
# define _LIBCPP_VERSION 190100
|
||||
|
||||
# define _LIBCPP_CONCAT_IMPL(_X, _Y) _X##_Y
|
||||
# define _LIBCPP_CONCAT(_X, _Y) _LIBCPP_CONCAT_IMPL(_X, _Y)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#define _LIBCPP___ITERATOR_BOUNDED_ITER_H
|
||||
|
||||
#include <__assert>
|
||||
#include <__compare/ordering.h>
|
||||
#include <__compare/three_way_comparable.h>
|
||||
#include <__config>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/pointer_traits.h>
|
||||
@@ -201,10 +203,15 @@ struct __bounded_iter {
|
||||
operator==(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
|
||||
return __x.__current_ == __y.__current_;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER <= 17
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
|
||||
operator!=(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
|
||||
return __x.__current_ != __y.__current_;
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(mordante) disable these overloads in the LLVM 20 release.
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR friend bool
|
||||
operator<(__bounded_iter const& __x, __bounded_iter const& __y) _NOEXCEPT {
|
||||
return __x.__current_ < __y.__current_;
|
||||
@@ -222,6 +229,23 @@ struct __bounded_iter {
|
||||
return __x.__current_ >= __y.__current_;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr friend strong_ordering
|
||||
operator<=>(__bounded_iter const& __x, __bounded_iter const& __y) noexcept {
|
||||
if constexpr (three_way_comparable<_Iterator, strong_ordering>) {
|
||||
return __x.__current_ <=> __y.__current_;
|
||||
} else {
|
||||
if (__x.__current_ < __y.__current_)
|
||||
return strong_ordering::less;
|
||||
|
||||
if (__x.__current_ == __y.__current_)
|
||||
return strong_ordering::equal;
|
||||
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
private:
|
||||
template <class>
|
||||
friend struct pointer_traits;
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#ifndef _LIBCPP___ITERATOR_WRAP_ITER_H
|
||||
#define _LIBCPP___ITERATOR_WRAP_ITER_H
|
||||
|
||||
#include <__compare/ordering.h>
|
||||
#include <__compare/three_way_comparable.h>
|
||||
#include <__config>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__memory/addressof.h>
|
||||
@@ -131,6 +133,7 @@ operator<(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXC
|
||||
return __x.base() < __y.base();
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER <= 17
|
||||
template <class _Iter1>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
|
||||
@@ -142,7 +145,9 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
|
||||
operator!=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEXCEPT {
|
||||
return !(__x == __y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(mordante) disable these overloads in the LLVM 20 release.
|
||||
template <class _Iter1>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool
|
||||
operator>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter1>& __y) _NOEXCEPT {
|
||||
@@ -179,6 +184,24 @@ operator<=(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) _NOEX
|
||||
return !(__y < __x);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr strong_ordering
|
||||
operator<=>(const __wrap_iter<_Iter1>& __x, const __wrap_iter<_Iter2>& __y) noexcept {
|
||||
if constexpr (three_way_comparable_with<_Iter1, _Iter2, strong_ordering>) {
|
||||
return __x.base() <=> __y.base();
|
||||
} else {
|
||||
if (__x.base() < __y.base())
|
||||
return strong_ordering::less;
|
||||
|
||||
if (__x.base() == __y.base())
|
||||
return strong_ordering::equal;
|
||||
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
template <class _Iter1, class _Iter2>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
|
||||
@@ -15,10 +15,21 @@
|
||||
#include <__type_traits/is_same.h>
|
||||
#include <__type_traits/promote.h>
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
# include <__algorithm/max.h>
|
||||
# include <__math/abs.h>
|
||||
# include <__math/roots.h>
|
||||
# include <__utility/pair.h>
|
||||
# include <limits>
|
||||
#endif
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
namespace __math {
|
||||
@@ -41,8 +52,86 @@ inline _LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2>::type hypot(_A1 __x, _
|
||||
return __math::hypot((__result_type)__x, (__result_type)__y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
// Factors needed to determine if over-/underflow might happen for `std::hypot(x,y,z)`.
|
||||
// returns [overflow_threshold, overflow_scale]
|
||||
template <class _Real>
|
||||
_LIBCPP_HIDE_FROM_ABI std::pair<_Real, _Real> __hypot_factors() {
|
||||
static_assert(std::numeric_limits<_Real>::is_iec559);
|
||||
|
||||
if constexpr (std::is_same_v<_Real, float>) {
|
||||
static_assert(-125 == std::numeric_limits<_Real>::min_exponent);
|
||||
static_assert(+128 == std::numeric_limits<_Real>::max_exponent);
|
||||
return {0x1.0p+62f, 0x1.0p-70f};
|
||||
} else if constexpr (std::is_same_v<_Real, double>) {
|
||||
static_assert(-1021 == std::numeric_limits<_Real>::min_exponent);
|
||||
static_assert(+1024 == std::numeric_limits<_Real>::max_exponent);
|
||||
return {0x1.0p+510, 0x1.0p-600};
|
||||
} else { // long double
|
||||
static_assert(std::is_same_v<_Real, long double>);
|
||||
|
||||
// preprocessor guard necessary, otherwise literals (e.g. `0x1.0p+8'190l`) throw warnings even when shielded by `if
|
||||
// constexpr`
|
||||
# if __DBL_MAX_EXP__ == __LDBL_MAX_EXP__
|
||||
static_assert(sizeof(_Real) == sizeof(double));
|
||||
return static_cast<std::pair<_Real, _Real>>(__math::__hypot_factors<double>());
|
||||
# else
|
||||
static_assert(sizeof(_Real) > sizeof(double));
|
||||
static_assert(-16381 == std::numeric_limits<_Real>::min_exponent);
|
||||
static_assert(+16384 == std::numeric_limits<_Real>::max_exponent);
|
||||
return {0x1.0p+8190l, 0x1.0p-9000l};
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
// Computes the three-dimensional hypotenuse: `std::hypot(x,y,z)`.
|
||||
// The naive implementation might over-/underflow which is why this implementation is more involved:
|
||||
// If the square of an argument might run into issues, we scale the arguments appropriately.
|
||||
// See https://github.com/llvm/llvm-project/issues/92782 for a detailed discussion and summary.
|
||||
template <class _Real>
|
||||
_LIBCPP_HIDE_FROM_ABI _Real __hypot(_Real __x, _Real __y, _Real __z) {
|
||||
const _Real __max_abs = std::max(__math::fabs(__x), std::max(__math::fabs(__y), __math::fabs(__z)));
|
||||
const auto [__overflow_threshold, __overflow_scale] = __math::__hypot_factors<_Real>();
|
||||
_Real __scale;
|
||||
if (__max_abs > __overflow_threshold) { // x*x + y*y + z*z might overflow
|
||||
__scale = __overflow_scale;
|
||||
__x *= __scale;
|
||||
__y *= __scale;
|
||||
__z *= __scale;
|
||||
} else if (__max_abs < 1 / __overflow_threshold) { // x*x + y*y + z*z might underflow
|
||||
__scale = 1 / __overflow_scale;
|
||||
__x *= __scale;
|
||||
__y *= __scale;
|
||||
__z *= __scale;
|
||||
} else
|
||||
__scale = 1;
|
||||
return __math::sqrt(__x * __x + __y * __y + __z * __z) / __scale;
|
||||
}
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y, float __z) { return __math::__hypot(__x, __y, __z); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y, double __z) { return __math::__hypot(__x, __y, __z); }
|
||||
|
||||
inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y, long double __z) {
|
||||
return __math::__hypot(__x, __y, __z);
|
||||
}
|
||||
|
||||
template <class _A1,
|
||||
class _A2,
|
||||
class _A3,
|
||||
std::enable_if_t< is_arithmetic_v<_A1> && is_arithmetic_v<_A2> && is_arithmetic_v<_A3>, int> = 0 >
|
||||
_LIBCPP_HIDE_FROM_ABI typename __promote<_A1, _A2, _A3>::type hypot(_A1 __x, _A2 __y, _A3 __z) _NOEXCEPT {
|
||||
using __result_type = typename __promote<_A1, _A2, _A3>::type;
|
||||
static_assert(!(
|
||||
std::is_same_v<_A1, __result_type> && std::is_same_v<_A2, __result_type> && std::is_same_v<_A3, __result_type>));
|
||||
return __math::__hypot(
|
||||
static_cast<__result_type>(__x), static_cast<__result_type>(__y), static_cast<__result_type>(__z));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace __math
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___MATH_HYPOT_H
|
||||
|
||||
+1
-24
@@ -313,6 +313,7 @@ constexpr long double lerp(long double a, long double b, long double t) noexcept
|
||||
*/
|
||||
|
||||
#include <__config>
|
||||
#include <__math/hypot.h>
|
||||
#include <__type_traits/enable_if.h>
|
||||
#include <__type_traits/is_arithmetic.h>
|
||||
#include <__type_traits/is_constant_evaluated.h>
|
||||
@@ -553,30 +554,6 @@ using ::scalbnl _LIBCPP_USING_IF_EXISTS;
|
||||
using ::tgammal _LIBCPP_USING_IF_EXISTS;
|
||||
using ::truncl _LIBCPP_USING_IF_EXISTS;
|
||||
|
||||
#if _LIBCPP_STD_VER >= 17
|
||||
inline _LIBCPP_HIDE_FROM_ABI float hypot(float __x, float __y, float __z) {
|
||||
return sqrt(__x * __x + __y * __y + __z * __z);
|
||||
}
|
||||
inline _LIBCPP_HIDE_FROM_ABI double hypot(double __x, double __y, double __z) {
|
||||
return sqrt(__x * __x + __y * __y + __z * __z);
|
||||
}
|
||||
inline _LIBCPP_HIDE_FROM_ABI long double hypot(long double __x, long double __y, long double __z) {
|
||||
return sqrt(__x * __x + __y * __y + __z * __z);
|
||||
}
|
||||
|
||||
template <class _A1, class _A2, class _A3>
|
||||
inline _LIBCPP_HIDE_FROM_ABI
|
||||
typename enable_if_t< is_arithmetic<_A1>::value && is_arithmetic<_A2>::value && is_arithmetic<_A3>::value,
|
||||
__promote<_A1, _A2, _A3> >::type
|
||||
hypot(_A1 __lcpp_x, _A2 __lcpp_y, _A3 __lcpp_z) _NOEXCEPT {
|
||||
typedef typename __promote<_A1, _A2, _A3>::type __result_type;
|
||||
static_assert(
|
||||
!(is_same<_A1, __result_type>::value && is_same<_A2, __result_type>::value && is_same<_A3, __result_type>::value),
|
||||
"");
|
||||
return std::hypot((__result_type)__lcpp_x, (__result_type)__lcpp_y, (__result_type)__lcpp_z);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0>
|
||||
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR bool __constexpr_isnan(_A1 __lcpp_x) _NOEXCEPT {
|
||||
#if __has_builtin(__builtin_isnan)
|
||||
|
||||
+27
-2
@@ -376,10 +376,13 @@ public:
|
||||
return __x.__ptr_ == __y.__ptr_;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER <= 17
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator!=(const __deque_iterator& __x, const __deque_iterator& __y) {
|
||||
return !(__x == __y);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(mordante) disable these overloads in the LLVM 20 release.
|
||||
_LIBCPP_HIDE_FROM_ABI friend bool operator<(const __deque_iterator& __x, const __deque_iterator& __y) {
|
||||
return __x.__m_iter_ < __y.__m_iter_ || (__x.__m_iter_ == __y.__m_iter_ && __x.__ptr_ < __y.__ptr_);
|
||||
}
|
||||
@@ -396,6 +399,29 @@ public:
|
||||
return !(__x < __y);
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER >= 20
|
||||
_LIBCPP_HIDE_FROM_ABI friend strong_ordering operator<=>(const __deque_iterator& __x, const __deque_iterator& __y) {
|
||||
if (__x.__m_iter_ < __y.__m_iter_)
|
||||
return strong_ordering::less;
|
||||
|
||||
if (__x.__m_iter_ == __y.__m_iter_) {
|
||||
if constexpr (three_way_comparable<pointer, strong_ordering>) {
|
||||
return __x.__ptr_ <=> __y.__ptr_;
|
||||
} else {
|
||||
if (__x.__ptr_ < __y.__ptr_)
|
||||
return strong_ordering::less;
|
||||
|
||||
if (__x.__ptr_ == __y.__ptr_)
|
||||
return strong_ordering::equal;
|
||||
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
}
|
||||
|
||||
return strong_ordering::greater;
|
||||
}
|
||||
#endif // _LIBCPP_STD_VER >= 20
|
||||
|
||||
private:
|
||||
_LIBCPP_HIDE_FROM_ABI explicit __deque_iterator(__map_iterator __m, pointer __p) _NOEXCEPT
|
||||
: __m_iter_(__m),
|
||||
@@ -2530,8 +2556,7 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator<=(const deque<_Tp, _Allocator>& __x,
|
||||
template <class _Tp, class _Allocator>
|
||||
_LIBCPP_HIDE_FROM_ABI __synth_three_way_result<_Tp>
|
||||
operator<=>(const deque<_Tp, _Allocator>& __x, const deque<_Tp, _Allocator>& __y) {
|
||||
return std::lexicographical_compare_three_way(
|
||||
__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
|
||||
return std::lexicographical_compare_three_way(__x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER <= 17
|
||||
|
||||
@@ -232,6 +232,10 @@ template <class charT> class messages_byname;
|
||||
# include <__locale_dir/locale_base_api/bsd_locale_fallbacks.h>
|
||||
# endif
|
||||
|
||||
# if defined(__APPLE__) || defined(__FreeBSD__)
|
||||
# include <xlocale.h>
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
# endif
|
||||
|
||||
+14
-3
@@ -3358,23 +3358,34 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
|
||||
__p = __get_long_pointer();
|
||||
} else {
|
||||
if (__target_capacity > __cap) {
|
||||
// Extend
|
||||
// - called from reserve should propagate the exception thrown.
|
||||
auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
|
||||
__new_data = __allocation.ptr;
|
||||
__target_capacity = __allocation.count - 1;
|
||||
} else {
|
||||
// Shrink
|
||||
// - called from shrink_to_fit should not throw.
|
||||
// - called from reserve may throw but is not required to.
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
try {
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
|
||||
|
||||
// The Standard mandates shrink_to_fit() does not increase the capacity.
|
||||
// With equal capacity keep the existing buffer. This avoids extra work
|
||||
// due to swapping the elements.
|
||||
if (__allocation.count - 1 > __target_capacity) {
|
||||
__alloc_traits::deallocate(__alloc(), __allocation.ptr, __allocation.count);
|
||||
__annotate_new(__sz); // Undoes the __annotate_delete()
|
||||
return;
|
||||
}
|
||||
__new_data = __allocation.ptr;
|
||||
__target_capacity = __allocation.count - 1;
|
||||
#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
} catch (...) {
|
||||
return;
|
||||
}
|
||||
#else // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
if (__new_data == nullptr)
|
||||
return;
|
||||
#endif // _LIBCPP_HAS_NO_EXCEPTIONS
|
||||
}
|
||||
__begin_lifetime(__new_data, __target_capacity + 1);
|
||||
|
||||
@@ -244,12 +244,23 @@ class AAQueryInfo {
|
||||
public:
|
||||
using LocPair = std::pair<AACacheLoc, AACacheLoc>;
|
||||
struct CacheEntry {
|
||||
/// Cache entry is neither an assumption nor does it use a (non-definitive)
|
||||
/// assumption.
|
||||
static constexpr int Definitive = -2;
|
||||
/// Cache entry is not an assumption itself, but may be using an assumption
|
||||
/// from higher up the stack.
|
||||
static constexpr int AssumptionBased = -1;
|
||||
|
||||
AliasResult Result;
|
||||
/// Number of times a NoAlias assumption has been used.
|
||||
/// 0 for assumptions that have not been used, -1 for definitive results.
|
||||
/// Number of times a NoAlias assumption has been used, 0 for assumptions
|
||||
/// that have not been used. Can also take one of the Definitive or
|
||||
/// AssumptionBased values documented above.
|
||||
int NumAssumptionUses;
|
||||
|
||||
/// Whether this is a definitive (non-assumption) result.
|
||||
bool isDefinitive() const { return NumAssumptionUses < 0; }
|
||||
bool isDefinitive() const { return NumAssumptionUses == Definitive; }
|
||||
/// Whether this is an assumption that has not been proven yet.
|
||||
bool isAssumption() const { return NumAssumptionUses >= 0; }
|
||||
};
|
||||
|
||||
// Alias analysis result aggregration using which this query is performed.
|
||||
|
||||
@@ -130,6 +130,12 @@ struct SimplifyQuery {
|
||||
Copy.CC = &CC;
|
||||
return Copy;
|
||||
}
|
||||
|
||||
SimplifyQuery getWithoutCondContext() const {
|
||||
SimplifyQuery Copy(*this);
|
||||
Copy.CC = nullptr;
|
||||
return Copy;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
@@ -251,7 +251,7 @@ class MachineFrameInfo {
|
||||
/// targets, this value is only used when generating debug info (via
|
||||
/// TargetRegisterInfo::getFrameIndexReference); when generating code, the
|
||||
/// corresponding adjustments are performed directly.
|
||||
int OffsetAdjustment = 0;
|
||||
int64_t OffsetAdjustment = 0;
|
||||
|
||||
/// The prolog/epilog code inserter may process objects that require greater
|
||||
/// alignment than the default alignment the target provides.
|
||||
@@ -280,7 +280,7 @@ class MachineFrameInfo {
|
||||
/// setup/destroy pseudo instructions (as defined in the TargetFrameInfo
|
||||
/// class). This information is important for frame pointer elimination.
|
||||
/// It is only valid during and after prolog/epilog code insertion.
|
||||
unsigned MaxCallFrameSize = ~0u;
|
||||
uint64_t MaxCallFrameSize = ~UINT64_C(0);
|
||||
|
||||
/// The number of bytes of callee saved registers that the target wants to
|
||||
/// report for the current function in the CodeView S_FRAMEPROC record.
|
||||
@@ -593,10 +593,10 @@ class MachineFrameInfo {
|
||||
uint64_t estimateStackSize(const MachineFunction &MF) const;
|
||||
|
||||
/// Return the correction for frame offsets.
|
||||
int getOffsetAdjustment() const { return OffsetAdjustment; }
|
||||
int64_t getOffsetAdjustment() const { return OffsetAdjustment; }
|
||||
|
||||
/// Set the correction for frame offsets.
|
||||
void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; }
|
||||
void setOffsetAdjustment(int64_t Adj) { OffsetAdjustment = Adj; }
|
||||
|
||||
/// Return the alignment in bytes that this function must be aligned to,
|
||||
/// which is greater than the default stack alignment provided by the target.
|
||||
@@ -663,7 +663,7 @@ class MachineFrameInfo {
|
||||
/// CallFrameSetup/Destroy pseudo instructions are used by the target, and
|
||||
/// then only during or after prolog/epilog code insertion.
|
||||
///
|
||||
unsigned getMaxCallFrameSize() const {
|
||||
uint64_t getMaxCallFrameSize() const {
|
||||
// TODO: Enable this assert when targets are fixed.
|
||||
//assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet");
|
||||
if (!isMaxCallFrameSizeComputed())
|
||||
@@ -671,9 +671,9 @@ class MachineFrameInfo {
|
||||
return MaxCallFrameSize;
|
||||
}
|
||||
bool isMaxCallFrameSizeComputed() const {
|
||||
return MaxCallFrameSize != ~0u;
|
||||
return MaxCallFrameSize != ~UINT64_C(0);
|
||||
}
|
||||
void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; }
|
||||
void setMaxCallFrameSize(uint64_t S) { MaxCallFrameSize = S; }
|
||||
|
||||
/// Returns how many bytes of callee-saved registers the target pushed in the
|
||||
/// prologue. Only used for debug info.
|
||||
|
||||
@@ -51,7 +51,7 @@ class TargetFrameLowering {
|
||||
// Maps a callee saved register to a stack slot with a fixed offset.
|
||||
struct SpillSlot {
|
||||
unsigned Reg;
|
||||
int Offset; // Offset relative to stack pointer on function entry.
|
||||
int64_t Offset; // Offset relative to stack pointer on function entry.
|
||||
};
|
||||
|
||||
struct DwarfFrameBase {
|
||||
@@ -66,7 +66,7 @@ class TargetFrameLowering {
|
||||
// Used with FrameBaseKind::Register.
|
||||
unsigned Reg;
|
||||
// Used with FrameBaseKind::CFA.
|
||||
int Offset;
|
||||
int64_t Offset;
|
||||
struct WasmFrameBase WasmLoc;
|
||||
} Location;
|
||||
};
|
||||
|
||||
@@ -225,7 +225,7 @@ class MCAsmBackend {
|
||||
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}
|
||||
|
||||
/// Generate the compact unwind encoding for the CFI instructions.
|
||||
virtual uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
virtual uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
const MCContext *Ctxt) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -509,11 +509,11 @@ class MCCFIInstruction {
|
||||
union {
|
||||
struct {
|
||||
unsigned Register;
|
||||
int Offset;
|
||||
int64_t Offset;
|
||||
} RI;
|
||||
struct {
|
||||
unsigned Register;
|
||||
int Offset;
|
||||
int64_t Offset;
|
||||
unsigned AddressSpace;
|
||||
} RIA;
|
||||
struct {
|
||||
@@ -527,7 +527,7 @@ class MCCFIInstruction {
|
||||
std::vector<char> Values;
|
||||
std::string Comment;
|
||||
|
||||
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, SMLoc Loc,
|
||||
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, SMLoc Loc,
|
||||
StringRef V = "", StringRef Comment = "")
|
||||
: Label(L), Operation(Op), Loc(Loc), Values(V.begin(), V.end()),
|
||||
Comment(Comment) {
|
||||
@@ -539,7 +539,7 @@ class MCCFIInstruction {
|
||||
assert(Op == OpRegister);
|
||||
U.RR = {R1, R2};
|
||||
}
|
||||
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int O, unsigned AS,
|
||||
MCCFIInstruction(OpType Op, MCSymbol *L, unsigned R, int64_t O, unsigned AS,
|
||||
SMLoc Loc)
|
||||
: Label(L), Operation(Op), Loc(Loc) {
|
||||
assert(Op == OpLLVMDefAspaceCfa);
|
||||
@@ -555,8 +555,8 @@ class MCCFIInstruction {
|
||||
public:
|
||||
/// .cfi_def_cfa defines a rule for computing CFA as: take address from
|
||||
/// Register and add Offset to it.
|
||||
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int Offset,
|
||||
SMLoc Loc = {}) {
|
||||
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register,
|
||||
int64_t Offset, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpDefCfa, L, Register, Offset, Loc);
|
||||
}
|
||||
|
||||
@@ -564,13 +564,13 @@ class MCCFIInstruction {
|
||||
/// on Register will be used instead of the old one. Offset remains the same.
|
||||
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpDefCfaRegister, L, Register, 0, Loc);
|
||||
return MCCFIInstruction(OpDefCfaRegister, L, Register, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_def_cfa_offset modifies a rule for computing CFA. Register
|
||||
/// remains the same, but offset is new. Note that it is the absolute offset
|
||||
/// that will be added to a defined register to the compute CFA address.
|
||||
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset,
|
||||
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpDefCfaOffset, L, 0, Offset, Loc);
|
||||
}
|
||||
@@ -578,7 +578,7 @@ class MCCFIInstruction {
|
||||
/// .cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but
|
||||
/// Offset is a relative value that is added/subtracted from the previous
|
||||
/// offset.
|
||||
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment,
|
||||
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int64_t Adjustment,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpAdjustCfaOffset, L, 0, Adjustment, Loc);
|
||||
}
|
||||
@@ -588,7 +588,7 @@ class MCCFIInstruction {
|
||||
/// be the result of evaluating the DWARF operation expression
|
||||
/// `DW_OP_constu AS; DW_OP_aspace_bregx R, B` as a location description.
|
||||
static MCCFIInstruction createLLVMDefAspaceCfa(MCSymbol *L, unsigned Register,
|
||||
int Offset,
|
||||
int64_t Offset,
|
||||
unsigned AddressSpace,
|
||||
SMLoc Loc) {
|
||||
return MCCFIInstruction(OpLLVMDefAspaceCfa, L, Register, Offset,
|
||||
@@ -598,7 +598,7 @@ class MCCFIInstruction {
|
||||
/// .cfi_offset Previous value of Register is saved at offset Offset
|
||||
/// from CFA.
|
||||
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register,
|
||||
int Offset, SMLoc Loc = {}) {
|
||||
int64_t Offset, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpOffset, L, Register, Offset, Loc);
|
||||
}
|
||||
|
||||
@@ -606,7 +606,7 @@ class MCCFIInstruction {
|
||||
/// Offset from the current CFA register. This is transformed to .cfi_offset
|
||||
/// using the known displacement of the CFA register from the CFA.
|
||||
static MCCFIInstruction createRelOffset(MCSymbol *L, unsigned Register,
|
||||
int Offset, SMLoc Loc = {}) {
|
||||
int64_t Offset, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpRelOffset, L, Register, Offset, Loc);
|
||||
}
|
||||
|
||||
@@ -619,12 +619,12 @@ class MCCFIInstruction {
|
||||
|
||||
/// .cfi_window_save SPARC register window is saved.
|
||||
static MCCFIInstruction createWindowSave(MCSymbol *L, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpWindowSave, L, 0, 0, Loc);
|
||||
return MCCFIInstruction(OpWindowSave, L, 0, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_negate_ra_state AArch64 negate RA state.
|
||||
static MCCFIInstruction createNegateRAState(MCSymbol *L, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpNegateRAState, L, 0, 0, Loc);
|
||||
return MCCFIInstruction(OpNegateRAState, L, 0, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_restore says that the rule for Register is now the same as it
|
||||
@@ -632,31 +632,31 @@ class MCCFIInstruction {
|
||||
/// by .cfi_startproc were executed.
|
||||
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpRestore, L, Register, 0, Loc);
|
||||
return MCCFIInstruction(OpRestore, L, Register, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_undefined From now on the previous value of Register can't be
|
||||
/// restored anymore.
|
||||
static MCCFIInstruction createUndefined(MCSymbol *L, unsigned Register,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpUndefined, L, Register, 0, Loc);
|
||||
return MCCFIInstruction(OpUndefined, L, Register, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_same_value Current value of Register is the same as in the
|
||||
/// previous frame. I.e., no restoration is needed.
|
||||
static MCCFIInstruction createSameValue(MCSymbol *L, unsigned Register,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpSameValue, L, Register, 0, Loc);
|
||||
return MCCFIInstruction(OpSameValue, L, Register, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_remember_state Save all current rules for all registers.
|
||||
static MCCFIInstruction createRememberState(MCSymbol *L, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpRememberState, L, 0, 0, Loc);
|
||||
return MCCFIInstruction(OpRememberState, L, 0, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_restore_state Restore the previously saved state.
|
||||
static MCCFIInstruction createRestoreState(MCSymbol *L, SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpRestoreState, L, 0, 0, Loc);
|
||||
return MCCFIInstruction(OpRestoreState, L, 0, INT64_C(0), Loc);
|
||||
}
|
||||
|
||||
/// .cfi_escape Allows the user to add arbitrary bytes to the unwind
|
||||
@@ -667,7 +667,7 @@ class MCCFIInstruction {
|
||||
}
|
||||
|
||||
/// A special wrapper for .cfi_escape that indicates GNU_ARGS_SIZE
|
||||
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int Size,
|
||||
static MCCFIInstruction createGnuArgsSize(MCSymbol *L, int64_t Size,
|
||||
SMLoc Loc = {}) {
|
||||
return MCCFIInstruction(OpGnuArgsSize, L, 0, Size, Loc);
|
||||
}
|
||||
@@ -702,7 +702,7 @@ class MCCFIInstruction {
|
||||
return U.RIA.AddressSpace;
|
||||
}
|
||||
|
||||
int getOffset() const {
|
||||
int64_t getOffset() const {
|
||||
if (Operation == OpLLVMDefAspaceCfa)
|
||||
return U.RIA.Offset;
|
||||
assert(Operation == OpDefCfa || Operation == OpOffset ||
|
||||
@@ -736,7 +736,7 @@ struct MCDwarfFrameInfo {
|
||||
unsigned CurrentCfaRegister = 0;
|
||||
unsigned PersonalityEncoding = 0;
|
||||
unsigned LsdaEncoding = 0;
|
||||
uint32_t CompactUnwindEncoding = 0;
|
||||
uint64_t CompactUnwindEncoding = 0;
|
||||
bool IsSignalFrame = false;
|
||||
bool IsSimple = false;
|
||||
unsigned RAReg = static_cast<unsigned>(INT_MAX);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#undef AIX_PPC8_VALUE
|
||||
#undef AIX_PPC9_VALUE
|
||||
#undef AIX_PPC10_VALUE
|
||||
#undef AIX_PPC11_VALUE
|
||||
#else
|
||||
#ifndef PPC_LNX_FEATURE
|
||||
#define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN)
|
||||
@@ -84,6 +85,7 @@
|
||||
#define AIX_PPC8_VALUE 0x00010000
|
||||
#define AIX_PPC9_VALUE 0x00020000
|
||||
#define AIX_PPC10_VALUE 0x00040000
|
||||
#define AIX_PPC11_VALUE 0x00080000
|
||||
|
||||
// __builtin_cpu_is() and __builtin_cpu_supports() are supported only on Power7 and up on AIX.
|
||||
// PPC_CPU(Name, Linux_SUPPORT_METHOD, LinuxID, AIX_SUPPORT_METHOD, AIXID)
|
||||
@@ -103,6 +105,7 @@ PPC_CPU("ppc476",SYS_CALL,44,BUILTIN_PPC_FALSE,0)
|
||||
PPC_CPU("power8",SYS_CALL,45,USE_SYS_CONF,AIX_PPC8_VALUE)
|
||||
PPC_CPU("power9",SYS_CALL,46,USE_SYS_CONF,AIX_PPC9_VALUE)
|
||||
PPC_CPU("power10",SYS_CALL,47,USE_SYS_CONF,AIX_PPC10_VALUE)
|
||||
PPC_CPU("power11",SYS_CALL,48,USE_SYS_CONF,AIX_PPC11_VALUE)
|
||||
#undef PPC_CPU
|
||||
|
||||
// PPC features on Linux:
|
||||
|
||||
@@ -1692,9 +1692,12 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
|
||||
if (!Pair.second) {
|
||||
auto &Entry = Pair.first->second;
|
||||
if (!Entry.isDefinitive()) {
|
||||
// Remember that we used an assumption.
|
||||
++Entry.NumAssumptionUses;
|
||||
// Remember that we used an assumption. This may either be a direct use
|
||||
// of an assumption, or a use of an entry that may itself be based on an
|
||||
// assumption.
|
||||
++AAQI.NumAssumptionUses;
|
||||
if (Entry.isAssumption())
|
||||
++Entry.NumAssumptionUses;
|
||||
}
|
||||
// Cache contains sorted {V1,V2} pairs but we should return original order.
|
||||
auto Result = Entry.Result;
|
||||
@@ -1722,7 +1725,6 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
|
||||
Entry.Result = Result;
|
||||
// Cache contains sorted {V1,V2} pairs.
|
||||
Entry.Result.swap(Swapped);
|
||||
Entry.NumAssumptionUses = -1;
|
||||
|
||||
// If the assumption has been disproven, remove any results that may have
|
||||
// been based on this assumption. Do this after the Entry updates above to
|
||||
@@ -1734,8 +1736,26 @@ AliasResult BasicAAResult::aliasCheck(const Value *V1, LocationSize V1Size,
|
||||
// The result may still be based on assumptions higher up in the chain.
|
||||
// Remember it, so it can be purged from the cache later.
|
||||
if (OrigNumAssumptionUses != AAQI.NumAssumptionUses &&
|
||||
Result != AliasResult::MayAlias)
|
||||
Result != AliasResult::MayAlias) {
|
||||
AAQI.AssumptionBasedResults.push_back(Locs);
|
||||
Entry.NumAssumptionUses = AAQueryInfo::CacheEntry::AssumptionBased;
|
||||
} else {
|
||||
Entry.NumAssumptionUses = AAQueryInfo::CacheEntry::Definitive;
|
||||
}
|
||||
|
||||
// Depth is incremented before this function is called, so Depth==1 indicates
|
||||
// a root query.
|
||||
if (AAQI.Depth == 1) {
|
||||
// Any remaining assumption based results must be based on proven
|
||||
// assumptions, so convert them to definitive results.
|
||||
for (const auto &Loc : AAQI.AssumptionBasedResults) {
|
||||
auto It = AAQI.AliasCache.find(Loc);
|
||||
if (It != AAQI.AliasCache.end())
|
||||
It->second.NumAssumptionUses = AAQueryInfo::CacheEntry::Definitive;
|
||||
}
|
||||
AAQI.AssumptionBasedResults.clear();
|
||||
AAQI.NumAssumptionUses = 0;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1435,7 +1435,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
// inferred hold at original context instruction. TODO: It may be
|
||||
// correct to use the original context. IF warranted, explore and
|
||||
// add sufficient tests to cover.
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
RecQ.CxtI = P;
|
||||
computeKnownBits(R, DemandedElts, Known2, Depth + 1, RecQ);
|
||||
switch (Opcode) {
|
||||
@@ -1468,7 +1468,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
// phi. This is important because that is where the value is actually
|
||||
// "evaluated" even though it is used later somewhere else. (see also
|
||||
// D69571).
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
|
||||
unsigned OpNum = P->getOperand(0) == R ? 0 : 1;
|
||||
Instruction *RInst = P->getIncomingBlock(OpNum)->getTerminator();
|
||||
@@ -1546,7 +1546,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
|
||||
// phi. This is important because that is where the value is actually
|
||||
// "evaluated" even though it is used later somewhere else. (see also
|
||||
// D69571).
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
RecQ.CxtI = P->getIncomingBlock(u)->getTerminator();
|
||||
|
||||
Known2 = KnownBits(BitWidth);
|
||||
@@ -2329,7 +2329,7 @@ bool isKnownToBeAPowerOfTwo(const Value *V, bool OrZero, unsigned Depth,
|
||||
// it is an induction variable where in each step its value is a power of
|
||||
// two.
|
||||
auto *PN = cast<PHINode>(I);
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
|
||||
// Check if it is an induction variable and always power of two.
|
||||
if (isPowerOfTwoRecurrence(PN, OrZero, Depth, RecQ))
|
||||
@@ -2943,7 +2943,7 @@ static bool isKnownNonZeroFromOperator(const Operator *I,
|
||||
return true;
|
||||
|
||||
// Check if all incoming values are non-zero using recursion.
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
unsigned NewDepth = std::max(Depth, MaxAnalysisRecursionDepth - 1);
|
||||
return llvm::all_of(PN->operands(), [&](const Use &U) {
|
||||
if (U.get() == PN)
|
||||
@@ -3509,7 +3509,7 @@ static bool isNonEqualPHIs(const PHINode *PN1, const PHINode *PN2,
|
||||
if (UsedFullRecursion)
|
||||
return false;
|
||||
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
RecQ.CxtI = IncomBB->getTerminator();
|
||||
if (!isKnownNonEqual(IV1, IV2, DemandedElts, Depth + 1, RecQ))
|
||||
return false;
|
||||
@@ -4001,7 +4001,7 @@ static unsigned ComputeNumSignBitsImpl(const Value *V,
|
||||
|
||||
// Take the minimum of all incoming values. This can't infinitely loop
|
||||
// because of our depth threshold.
|
||||
SimplifyQuery RecQ = Q;
|
||||
SimplifyQuery RecQ = Q.getWithoutCondContext();
|
||||
Tmp = TyBits;
|
||||
for (unsigned i = 0, e = NumIncomingValues; i != e; ++i) {
|
||||
if (Tmp == 1) return Tmp;
|
||||
@@ -5909,10 +5909,10 @@ void computeKnownFPClass(const Value *V, const APInt &DemandedElts,
|
||||
// Recurse, but cap the recursion to two levels, because we don't want
|
||||
// to waste time spinning around in loops. We need at least depth 2 to
|
||||
// detect known sign bits.
|
||||
computeKnownFPClass(
|
||||
IncValue, DemandedElts, InterestedClasses, KnownSrc,
|
||||
PhiRecursionLimit,
|
||||
Q.getWithInstruction(P->getIncomingBlock(U)->getTerminator()));
|
||||
computeKnownFPClass(IncValue, DemandedElts, InterestedClasses, KnownSrc,
|
||||
PhiRecursionLimit,
|
||||
Q.getWithoutCondContext().getWithInstruction(
|
||||
P->getIncomingBlock(U)->getTerminator()));
|
||||
|
||||
if (First) {
|
||||
Known = KnownSrc;
|
||||
|
||||
@@ -68,9 +68,9 @@ class CFIInstrInserter : public MachineFunctionPass {
|
||||
struct MBBCFAInfo {
|
||||
MachineBasicBlock *MBB;
|
||||
/// Value of cfa offset valid at basic block entry.
|
||||
int IncomingCFAOffset = -1;
|
||||
int64_t IncomingCFAOffset = -1;
|
||||
/// Value of cfa offset valid at basic block exit.
|
||||
int OutgoingCFAOffset = -1;
|
||||
int64_t OutgoingCFAOffset = -1;
|
||||
/// Value of cfa register valid at basic block entry.
|
||||
unsigned IncomingCFARegister = 0;
|
||||
/// Value of cfa register valid at basic block exit.
|
||||
@@ -120,7 +120,7 @@ class CFIInstrInserter : public MachineFunctionPass {
|
||||
/// Return the cfa offset value that should be set at the beginning of a MBB
|
||||
/// if needed. The negated value is needed when creating CFI instructions that
|
||||
/// set absolute offset.
|
||||
int getCorrectCFAOffset(MachineBasicBlock *MBB) {
|
||||
int64_t getCorrectCFAOffset(MachineBasicBlock *MBB) {
|
||||
return MBBVector[MBB->getNumber()].IncomingCFAOffset;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ void CFIInstrInserter::calculateCFAInfo(MachineFunction &MF) {
|
||||
|
||||
void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
|
||||
// Outgoing cfa offset set by the block.
|
||||
int SetOffset = MBBInfo.IncomingCFAOffset;
|
||||
int64_t SetOffset = MBBInfo.IncomingCFAOffset;
|
||||
// Outgoing cfa register set by the block.
|
||||
unsigned SetRegister = MBBInfo.IncomingCFARegister;
|
||||
MachineFunction *MF = MBBInfo.MBB->getParent();
|
||||
@@ -188,7 +188,7 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
|
||||
for (MachineInstr &MI : *MBBInfo.MBB) {
|
||||
if (MI.isCFIInstruction()) {
|
||||
std::optional<unsigned> CSRReg;
|
||||
std::optional<int> CSROffset;
|
||||
std::optional<int64_t> CSROffset;
|
||||
unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
|
||||
const MCCFIInstruction &CFI = Instrs[CFIIndex];
|
||||
switch (CFI.getOperation()) {
|
||||
|
||||
@@ -197,7 +197,7 @@ void MachineFrameInfo::computeMaxCallFrameSize(
|
||||
for (MachineInstr &MI : MBB) {
|
||||
unsigned Opcode = MI.getOpcode();
|
||||
if (Opcode == FrameSetupOpcode || Opcode == FrameDestroyOpcode) {
|
||||
unsigned Size = TII.getFrameSize(MI);
|
||||
uint64_t Size = TII.getFrameSize(MI);
|
||||
MaxCallFrameSize = std::max(MaxCallFrameSize, Size);
|
||||
if (FrameSDOps != nullptr)
|
||||
FrameSDOps->push_back(&MI);
|
||||
|
||||
@@ -366,8 +366,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &MF) {
|
||||
return;
|
||||
|
||||
// (Re-)Compute the MaxCallFrameSize.
|
||||
[[maybe_unused]] uint32_t MaxCFSIn =
|
||||
MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT32_MAX;
|
||||
[[maybe_unused]] uint64_t MaxCFSIn =
|
||||
MFI.isMaxCallFrameSizeComputed() ? MFI.getMaxCallFrameSize() : UINT64_MAX;
|
||||
std::vector<MachineBasicBlock::iterator> FrameSDOps;
|
||||
MFI.computeMaxCallFrameSize(MF, &FrameSDOps);
|
||||
assert(MFI.getMaxCallFrameSize() <= MaxCFSIn &&
|
||||
|
||||
@@ -1299,8 +1299,8 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol,
|
||||
namespace {
|
||||
|
||||
class FrameEmitterImpl {
|
||||
int CFAOffset = 0;
|
||||
int InitialCFAOffset = 0;
|
||||
int64_t CFAOffset = 0;
|
||||
int64_t InitialCFAOffset = 0;
|
||||
bool IsEH;
|
||||
MCObjectStreamer &Streamer;
|
||||
|
||||
@@ -1414,7 +1414,7 @@ void FrameEmitterImpl::emitCFIInstruction(const MCCFIInstruction &Instr) {
|
||||
if (!IsEH)
|
||||
Reg = MRI->getDwarfRegNumFromDwarfEHRegNum(Reg);
|
||||
|
||||
int Offset = Instr.getOffset();
|
||||
int64_t Offset = Instr.getOffset();
|
||||
if (IsRelative)
|
||||
Offset -= CFAOffset;
|
||||
Offset = Offset / dataAlignmentFactor;
|
||||
|
||||
@@ -1080,6 +1080,10 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
|
||||
// Try to create BICs for vector ANDs.
|
||||
setTargetDAGCombine(ISD::AND);
|
||||
|
||||
// llvm.init.trampoline and llvm.adjust.trampoline
|
||||
setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom);
|
||||
setOperationAction(ISD::ADJUST_TRAMPOLINE, MVT::Other, Custom);
|
||||
|
||||
// Vector add and sub nodes may conceal a high-half opportunity.
|
||||
// Also, try to fold ADD into CSINC/CSINV..
|
||||
setTargetDAGCombine({ISD::ADD, ISD::ABS, ISD::SUB, ISD::XOR, ISD::SINT_TO_FP,
|
||||
@@ -6688,6 +6692,56 @@ static SDValue LowerFLDEXP(SDValue Op, SelectionDAG &DAG) {
|
||||
return Final;
|
||||
}
|
||||
|
||||
SDValue AArch64TargetLowering::LowerADJUST_TRAMPOLINE(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
// Note: x18 cannot be used for the Nest parameter on Windows and macOS.
|
||||
if (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
|
||||
report_fatal_error(
|
||||
"ADJUST_TRAMPOLINE operation is only supported on Linux.");
|
||||
|
||||
return Op.getOperand(0);
|
||||
}
|
||||
|
||||
SDValue AArch64TargetLowering::LowerINIT_TRAMPOLINE(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
|
||||
// Note: x18 cannot be used for the Nest parameter on Windows and macOS.
|
||||
if (Subtarget->isTargetDarwin() || Subtarget->isTargetWindows())
|
||||
report_fatal_error("INIT_TRAMPOLINE operation is only supported on Linux.");
|
||||
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Trmp = Op.getOperand(1); // trampoline
|
||||
SDValue FPtr = Op.getOperand(2); // nested function
|
||||
SDValue Nest = Op.getOperand(3); // 'nest' parameter value
|
||||
SDLoc dl(Op);
|
||||
|
||||
EVT PtrVT = getPointerTy(DAG.getDataLayout());
|
||||
Type *IntPtrTy = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
|
||||
|
||||
TargetLowering::ArgListTy Args;
|
||||
TargetLowering::ArgListEntry Entry;
|
||||
|
||||
Entry.Ty = IntPtrTy;
|
||||
Entry.Node = Trmp;
|
||||
Args.push_back(Entry);
|
||||
Entry.Node = DAG.getConstant(20, dl, MVT::i64);
|
||||
Args.push_back(Entry);
|
||||
|
||||
Entry.Node = FPtr;
|
||||
Args.push_back(Entry);
|
||||
Entry.Node = Nest;
|
||||
Args.push_back(Entry);
|
||||
|
||||
// Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg)
|
||||
TargetLowering::CallLoweringInfo CLI(DAG);
|
||||
CLI.setDebugLoc(dl).setChain(Chain).setLibCallee(
|
||||
CallingConv::C, Type::getVoidTy(*DAG.getContext()),
|
||||
DAG.getExternalSymbol("__trampoline_setup", PtrVT), std::move(Args));
|
||||
|
||||
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
|
||||
return CallResult.second;
|
||||
}
|
||||
|
||||
SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
LLVM_DEBUG(dbgs() << "Custom lowering: ");
|
||||
@@ -6705,6 +6759,10 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
|
||||
return LowerGlobalTLSAddress(Op, DAG);
|
||||
case ISD::PtrAuthGlobalAddress:
|
||||
return LowerPtrAuthGlobalAddress(Op, DAG);
|
||||
case ISD::ADJUST_TRAMPOLINE:
|
||||
return LowerADJUST_TRAMPOLINE(Op, DAG);
|
||||
case ISD::INIT_TRAMPOLINE:
|
||||
return LowerINIT_TRAMPOLINE(Op, DAG);
|
||||
case ISD::SETCC:
|
||||
case ISD::STRICT_FSETCC:
|
||||
case ISD::STRICT_FSETCCS:
|
||||
|
||||
@@ -1143,6 +1143,8 @@ class AArch64TargetLowering : public TargetLowering {
|
||||
SDValue LowerSELECT_CC(ISD::CondCode CC, SDValue LHS, SDValue RHS,
|
||||
SDValue TVal, SDValue FVal, const SDLoc &dl,
|
||||
SelectionDAG &DAG) const;
|
||||
SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerBRIND(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
@@ -8339,7 +8339,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
|
||||
NumBytesToCreateFrame += 8;
|
||||
|
||||
// PAuth is enabled - set extra tail call cost, if any.
|
||||
auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod();
|
||||
auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
|
||||
*RepeatedSequenceLocs[0].getMF());
|
||||
NumBytesToCheckLRInTCEpilogue =
|
||||
AArch64PAuth::getCheckerSizeInBytes(LRCheckMethod);
|
||||
// Checking the authenticated LR value may significantly impact
|
||||
@@ -8700,6 +8701,10 @@ void AArch64InstrInfo::mergeOutliningCandidateAttributes(
|
||||
// behaviour of one of them
|
||||
const auto &CFn = Candidates.front().getMF()->getFunction();
|
||||
|
||||
if (CFn.hasFnAttribute("ptrauth-returns"))
|
||||
F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
|
||||
if (CFn.hasFnAttribute("ptrauth-auth-traps"))
|
||||
F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
|
||||
// Since all candidates belong to the same module, just copy the
|
||||
// function-level attributes of an arbitrary function.
|
||||
if (CFn.hasFnAttribute("sign-return-address"))
|
||||
|
||||
@@ -38,6 +38,8 @@ void AArch64FunctionInfo::initializeBaseYamlFields(
|
||||
}
|
||||
|
||||
static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
|
||||
if (F.hasFnAttribute("ptrauth-returns"))
|
||||
return {true, false}; // non-leaf
|
||||
// The function should be signed in the following situations:
|
||||
// - sign-return-address=all
|
||||
// - sign-return-address=non-leaf and the functions spills the LR
|
||||
@@ -56,6 +58,8 @@ static std::pair<bool, bool> GetSignReturnAddress(const Function &F) {
|
||||
}
|
||||
|
||||
static bool ShouldSignWithBKey(const Function &F, const AArch64Subtarget &STI) {
|
||||
if (F.hasFnAttribute("ptrauth-returns"))
|
||||
return true;
|
||||
if (!F.hasFnAttribute("sign-return-address-key")) {
|
||||
if (STI.getTargetTriple().isOSWindows())
|
||||
return true;
|
||||
|
||||
@@ -341,7 +341,8 @@ bool AArch64PointerAuth::checkAuthenticatedLR(
|
||||
AArch64PACKey::ID KeyId =
|
||||
MFnI->shouldSignWithBKey() ? AArch64PACKey::IB : AArch64PACKey::IA;
|
||||
|
||||
AuthCheckMethod Method = Subtarget->getAuthenticatedLRCheckMethod();
|
||||
AuthCheckMethod Method =
|
||||
Subtarget->getAuthenticatedLRCheckMethod(*TI->getMF());
|
||||
|
||||
if (Method == AuthCheckMethod::None)
|
||||
return false;
|
||||
|
||||
@@ -565,8 +565,13 @@ bool AArch64Subtarget::useAA() const { return UseAA; }
|
||||
// exception on its own. Later, if the callee spills the signed LR value and
|
||||
// neither FEAT_PAuth2 nor FEAT_EPAC are implemented, the valid PAC replaces
|
||||
// the higher bits of LR thus hiding the authentication failure.
|
||||
AArch64PAuth::AuthCheckMethod
|
||||
AArch64Subtarget::getAuthenticatedLRCheckMethod() const {
|
||||
AArch64PAuth::AuthCheckMethod AArch64Subtarget::getAuthenticatedLRCheckMethod(
|
||||
const MachineFunction &MF) const {
|
||||
// TODO: Check subtarget for the scheme. Present variant is a default for
|
||||
// pauthtest ABI.
|
||||
if (MF.getFunction().hasFnAttribute("ptrauth-returns") &&
|
||||
MF.getFunction().hasFnAttribute("ptrauth-auth-traps"))
|
||||
return AArch64PAuth::AuthCheckMethod::HighBitsNoTBI;
|
||||
if (AuthenticatedLRCheckMethod.getNumOccurrences())
|
||||
return AuthenticatedLRCheckMethod;
|
||||
|
||||
|
||||
@@ -413,7 +413,8 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
|
||||
}
|
||||
|
||||
/// Choose a method of checking LR before performing a tail call.
|
||||
AArch64PAuth::AuthCheckMethod getAuthenticatedLRCheckMethod() const;
|
||||
AArch64PAuth::AuthCheckMethod
|
||||
getAuthenticatedLRCheckMethod(const MachineFunction &MF) const;
|
||||
|
||||
/// Compute the integer discriminator for a given BlockAddress constant, if
|
||||
/// blockaddress signing is enabled, or std::nullopt otherwise.
|
||||
|
||||
@@ -599,7 +599,7 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
||||
}
|
||||
|
||||
/// Generate the compact unwind encoding from the CFI directives.
|
||||
uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
const MCContext *Ctxt) const override {
|
||||
ArrayRef<MCCFIInstruction> Instrs = FI->Instructions;
|
||||
if (Instrs.empty())
|
||||
@@ -609,10 +609,10 @@ class DarwinAArch64AsmBackend : public AArch64AsmBackend {
|
||||
return CU::UNWIND_ARM64_MODE_DWARF;
|
||||
|
||||
bool HasFP = false;
|
||||
unsigned StackSize = 0;
|
||||
uint64_t StackSize = 0;
|
||||
|
||||
uint32_t CompactUnwindEncoding = 0;
|
||||
int CurOffset = 0;
|
||||
uint64_t CompactUnwindEncoding = 0;
|
||||
int64_t CurOffset = 0;
|
||||
for (size_t i = 0, e = Instrs.size(); i != e; ++i) {
|
||||
const MCCFIInstruction &Inst = Instrs[i];
|
||||
|
||||
|
||||
@@ -1166,7 +1166,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
if (STI.splitFramePushPop(MF)) {
|
||||
unsigned DwarfReg = MRI->getDwarfRegNum(
|
||||
Reg == ARM::R12 ? ARM::RA_AUTH_CODE : Reg, true);
|
||||
unsigned Offset = MFI.getObjectOffset(FI);
|
||||
int64_t Offset = MFI.getObjectOffset(FI);
|
||||
unsigned CFIIndex = MF.addFrameInst(
|
||||
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
|
||||
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
||||
@@ -1188,7 +1188,7 @@ void ARMFrameLowering::emitPrologue(MachineFunction &MF,
|
||||
if ((Reg >= ARM::D0 && Reg <= ARM::D31) &&
|
||||
(Reg < ARM::D8 || Reg >= ARM::D8 + AFI->getNumAlignedDPRCS2Regs())) {
|
||||
unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
|
||||
unsigned Offset = MFI.getObjectOffset(FI);
|
||||
int64_t Offset = MFI.getObjectOffset(FI);
|
||||
unsigned CFIIndex = MF.addFrameInst(
|
||||
MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
|
||||
BuildMI(MBB, Pos, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
||||
|
||||
@@ -1146,7 +1146,7 @@ enum CompactUnwindEncodings {
|
||||
/// instructions. If the CFI instructions describe a frame that cannot be
|
||||
/// encoded in compact unwind, the method returns UNWIND_ARM_MODE_DWARF which
|
||||
/// tells the runtime to fallback and unwind using dwarf.
|
||||
uint32_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
|
||||
uint64_t ARMAsmBackendDarwin::generateCompactUnwindEncoding(
|
||||
const MCDwarfFrameInfo *FI, const MCContext *Ctxt) const {
|
||||
DEBUG_WITH_TYPE("compact-unwind", llvm::dbgs() << "generateCU()\n");
|
||||
// Only armv7k uses CFI based unwinding.
|
||||
|
||||
@@ -34,7 +34,7 @@ class ARMAsmBackendDarwin : public ARMAsmBackend {
|
||||
/*Is64Bit=*/false, cantFail(MachO::getCPUType(TT)), Subtype);
|
||||
}
|
||||
|
||||
uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
const MCContext *Ctxt) const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
@@ -670,8 +670,7 @@ class ARMELFStreamer : public MCELFStreamer {
|
||||
}
|
||||
|
||||
void EmitMappingSymbol(StringRef Name) {
|
||||
auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
|
||||
Name + "." + Twine(MappingSymbolCounter++)));
|
||||
auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
|
||||
emitLabel(Symbol);
|
||||
|
||||
Symbol->setType(ELF::STT_NOTYPE);
|
||||
@@ -679,8 +678,7 @@ class ARMELFStreamer : public MCELFStreamer {
|
||||
}
|
||||
|
||||
void emitMappingSymbol(StringRef Name, MCDataFragment &F, uint64_t Offset) {
|
||||
auto *Symbol = cast<MCSymbolELF>(getContext().getOrCreateSymbol(
|
||||
Name + "." + Twine(MappingSymbolCounter++)));
|
||||
auto *Symbol = cast<MCSymbolELF>(getContext().createLocalSymbol(Name));
|
||||
emitLabelAtPos(Symbol, SMLoc(), F, Offset);
|
||||
Symbol->setType(ELF::STT_NOTYPE);
|
||||
Symbol->setBinding(ELF::STB_LOCAL);
|
||||
@@ -710,7 +708,6 @@ class ARMELFStreamer : public MCELFStreamer {
|
||||
|
||||
bool IsThumb;
|
||||
bool IsAndroid;
|
||||
int64_t MappingSymbolCounter = 0;
|
||||
|
||||
DenseMap<const MCSection *, std::unique_ptr<ElfMappingSymbolInfo>>
|
||||
LastMappingSymbols;
|
||||
@@ -1121,7 +1118,6 @@ void ARMELFStreamer::reset() {
|
||||
MCTargetStreamer &TS = *getTargetStreamer();
|
||||
ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
|
||||
ATS.reset();
|
||||
MappingSymbolCounter = 0;
|
||||
MCELFStreamer::reset();
|
||||
LastMappingSymbols.clear();
|
||||
LastEMSInfo.reset();
|
||||
|
||||
@@ -1659,7 +1659,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
|
||||
using SpillSlot = TargetFrameLowering::SpillSlot;
|
||||
|
||||
unsigned NumFixed;
|
||||
int MinOffset = 0; // CS offsets are negative.
|
||||
int64_t MinOffset = 0; // CS offsets are negative.
|
||||
const SpillSlot *FixedSlots = getCalleeSavedSpillSlots(NumFixed);
|
||||
for (const SpillSlot *S = FixedSlots; S != FixedSlots+NumFixed; ++S) {
|
||||
if (!SRegs[S->Reg])
|
||||
@@ -1678,7 +1678,7 @@ bool HexagonFrameLowering::assignCalleeSavedSpillSlots(MachineFunction &MF,
|
||||
Register R = x;
|
||||
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(R);
|
||||
unsigned Size = TRI->getSpillSize(*RC);
|
||||
int Off = MinOffset - Size;
|
||||
int64_t Off = MinOffset - Size;
|
||||
Align Alignment = std::min(TRI->getSpillAlign(*RC), getStackAlign());
|
||||
Off &= -Alignment.value();
|
||||
int FI = MFI.CreateFixedSpillStackObject(Size, Off);
|
||||
|
||||
@@ -1144,7 +1144,6 @@ def : PatGprGpr<urem, MOD_DU>;
|
||||
def : PatGprGpr<loongarch_mod_wu, MOD_WU>;
|
||||
def : PatGprGpr<rotr, ROTR_D>;
|
||||
def : PatGprGpr<loongarch_rotr_w, ROTR_W>;
|
||||
def : PatGprGpr_32<rotr, ROTR_W>;
|
||||
def : PatGprImm<rotr, ROTRI_D, uimm6>;
|
||||
def : PatGprImm_32<rotr, ROTRI_W, uimm5>;
|
||||
def : PatGprImm<loongarch_rotr_w, ROTRI_W, uimm5>;
|
||||
|
||||
@@ -293,7 +293,7 @@ void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
if (!hasFP(MF)) {
|
||||
MBBI = FirstCSPop;
|
||||
int64_t Offset = -CSSize - 2;
|
||||
int64_t Offset = -(int64_t)CSSize - 2;
|
||||
// Mark callee-saved pop instruction.
|
||||
// Define the current CFA rule to use the provided offset.
|
||||
while (MBBI != MBB.end()) {
|
||||
|
||||
@@ -1429,7 +1429,6 @@ std::string NVPTXTargetLowering::getPrototype(
|
||||
|
||||
bool first = true;
|
||||
|
||||
const Function *F = CB.getFunction();
|
||||
unsigned NumArgs = VAInfo ? VAInfo->first : Args.size();
|
||||
for (unsigned i = 0, OIdx = 0; i != NumArgs; ++i, ++OIdx) {
|
||||
Type *Ty = Args[i].Ty;
|
||||
@@ -1471,10 +1470,12 @@ std::string NVPTXTargetLowering::getPrototype(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Indirect calls need strict ABI alignment so we disable optimizations by
|
||||
// not providing a function to optimize.
|
||||
Type *ETy = Args[i].IndirectType;
|
||||
Align InitialAlign = Outs[OIdx].Flags.getNonZeroByValAlign();
|
||||
Align ParamByValAlign =
|
||||
getFunctionByValParamAlign(F, ETy, InitialAlign, DL);
|
||||
getFunctionByValParamAlign(/*F=*/nullptr, ETy, InitialAlign, DL);
|
||||
|
||||
O << ".param .align " << ParamByValAlign.value() << " .b8 ";
|
||||
O << "_";
|
||||
|
||||
@@ -52,6 +52,7 @@ def DirectivePwr7: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR7", "">;
|
||||
def DirectivePwr8: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR8", "">;
|
||||
def DirectivePwr9: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR9", "">;
|
||||
def DirectivePwr10: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR10", "">;
|
||||
def DirectivePwr11: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR11", "">;
|
||||
def DirectivePwrFuture
|
||||
: SubtargetFeature<"", "CPUDirective", "PPC::DIR_PWR_FUTURE", "">;
|
||||
|
||||
@@ -467,13 +468,25 @@ def ProcessorFeatures {
|
||||
list<SubtargetFeature> P10Features =
|
||||
!listconcat(P10InheritableFeatures, P10SpecificFeatures);
|
||||
|
||||
// Future
|
||||
// For future CPU we assume that all of the existing features from Power10
|
||||
// Power11
|
||||
// For P11 CPU we assume that all the existing features from Power10
|
||||
// still exist with the exception of those we know are Power10 specific.
|
||||
list<SubtargetFeature> P11AdditionalFeatures =
|
||||
[DirectivePwr11];
|
||||
list<SubtargetFeature> P11SpecificFeatures =
|
||||
[];
|
||||
list<SubtargetFeature> P11InheritableFeatures =
|
||||
!listconcat(P10InheritableFeatures, P11AdditionalFeatures);
|
||||
list<SubtargetFeature> P11Features =
|
||||
!listconcat(P11InheritableFeatures, P11SpecificFeatures);
|
||||
|
||||
// Future
|
||||
// For future CPU we assume that all of the existing features from Power11
|
||||
// still exist with the exception of those we know are Power11 specific.
|
||||
list<SubtargetFeature> FutureAdditionalFeatures = [FeatureISAFuture];
|
||||
list<SubtargetFeature> FutureSpecificFeatures = [];
|
||||
list<SubtargetFeature> FutureInheritableFeatures =
|
||||
!listconcat(P10InheritableFeatures, FutureAdditionalFeatures);
|
||||
!listconcat(P11InheritableFeatures, FutureAdditionalFeatures);
|
||||
list<SubtargetFeature> FutureFeatures =
|
||||
!listconcat(FutureInheritableFeatures, FutureSpecificFeatures);
|
||||
}
|
||||
@@ -672,6 +685,7 @@ def : ProcessorModel<"pwr7", P7Model, ProcessorFeatures.P7Features>;
|
||||
def : ProcessorModel<"pwr8", P8Model, ProcessorFeatures.P8Features>;
|
||||
def : ProcessorModel<"pwr9", P9Model, ProcessorFeatures.P9Features>;
|
||||
def : ProcessorModel<"pwr10", P10Model, ProcessorFeatures.P10Features>;
|
||||
def : ProcessorModel<"pwr11", P10Model, ProcessorFeatures.P11Features>;
|
||||
// No scheduler model for future CPU.
|
||||
def : ProcessorModel<"future", NoSchedModel,
|
||||
ProcessorFeatures.FutureFeatures>;
|
||||
|
||||
@@ -1469,6 +1469,7 @@ PPCTargetLowering::PPCTargetLowering(const PPCTargetMachine &TM,
|
||||
case PPC::DIR_PWR8:
|
||||
case PPC::DIR_PWR9:
|
||||
case PPC::DIR_PWR10:
|
||||
case PPC::DIR_PWR11:
|
||||
case PPC::DIR_PWR_FUTURE:
|
||||
setPrefLoopAlignment(Align(16));
|
||||
setPrefFunctionAlignment(Align(16));
|
||||
@@ -16664,6 +16665,7 @@ Align PPCTargetLowering::getPrefLoopAlignment(MachineLoop *ML) const {
|
||||
case PPC::DIR_PWR8:
|
||||
case PPC::DIR_PWR9:
|
||||
case PPC::DIR_PWR10:
|
||||
case PPC::DIR_PWR11:
|
||||
case PPC::DIR_PWR_FUTURE: {
|
||||
if (!ML)
|
||||
break;
|
||||
@@ -18046,6 +18048,7 @@ SDValue PPCTargetLowering::combineMUL(SDNode *N, DAGCombinerInfo &DCI) const {
|
||||
return true;
|
||||
case PPC::DIR_PWR9:
|
||||
case PPC::DIR_PWR10:
|
||||
case PPC::DIR_PWR11:
|
||||
case PPC::DIR_PWR_FUTURE:
|
||||
// type mul add shl
|
||||
// scalar 5 2 2
|
||||
|
||||
@@ -3485,6 +3485,7 @@ unsigned PPCInstrInfo::getSpillTarget() const {
|
||||
// With P10, we may need to spill paired vector registers or accumulator
|
||||
// registers. MMA implies paired vectors, so we can just check that.
|
||||
bool IsP10Variant = Subtarget.isISA3_1() || Subtarget.pairedVectorMemops();
|
||||
// P11 uses the P10 target.
|
||||
return Subtarget.isISAFuture() ? 3 : IsP10Variant ?
|
||||
2 : Subtarget.hasP9Vector() ?
|
||||
1 : 0;
|
||||
|
||||
@@ -61,6 +61,7 @@ enum {
|
||||
DIR_PWR8,
|
||||
DIR_PWR9,
|
||||
DIR_PWR10,
|
||||
DIR_PWR11,
|
||||
DIR_PWR_FUTURE,
|
||||
DIR_64
|
||||
};
|
||||
|
||||
@@ -504,7 +504,7 @@ unsigned PPCTTIImpl::getCacheLineSize() const {
|
||||
// Assume that Future CPU has the same cache line size as the others.
|
||||
if (Directive == PPC::DIR_PWR7 || Directive == PPC::DIR_PWR8 ||
|
||||
Directive == PPC::DIR_PWR9 || Directive == PPC::DIR_PWR10 ||
|
||||
Directive == PPC::DIR_PWR_FUTURE)
|
||||
Directive == PPC::DIR_PWR11 || Directive == PPC::DIR_PWR_FUTURE)
|
||||
return 128;
|
||||
|
||||
// On other processors return a default of 64 bytes.
|
||||
@@ -538,7 +538,7 @@ unsigned PPCTTIImpl::getMaxInterleaveFactor(ElementCount VF) {
|
||||
// Assume that future is the same as the others.
|
||||
if (Directive == PPC::DIR_PWR7 || Directive == PPC::DIR_PWR8 ||
|
||||
Directive == PPC::DIR_PWR9 || Directive == PPC::DIR_PWR10 ||
|
||||
Directive == PPC::DIR_PWR_FUTURE)
|
||||
Directive == PPC::DIR_PWR11 || Directive == PPC::DIR_PWR_FUTURE)
|
||||
return 12;
|
||||
|
||||
// For most things, modern systems have two execution units (and
|
||||
|
||||
@@ -764,9 +764,9 @@ def InsnCR : DirectiveInsnCR<(outs AnyReg:$rd), (ins uimm2_opcode:$opcode,
|
||||
uimm4:$funct4,
|
||||
AnyReg:$rs2),
|
||||
"$opcode, $funct4, $rd, $rs2">;
|
||||
def InsnCI : DirectiveInsnCI<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
|
||||
uimm3:$funct3,
|
||||
simm6:$imm6),
|
||||
def InsnCI : DirectiveInsnCI<(outs AnyReg:$rd), (ins uimm2_opcode:$opcode,
|
||||
uimm3:$funct3,
|
||||
simm6:$imm6),
|
||||
"$opcode, $funct3, $rd, $imm6">;
|
||||
def InsnCIW : DirectiveInsnCIW<(outs AnyRegC:$rd), (ins uimm2_opcode:$opcode,
|
||||
uimm3:$funct3,
|
||||
@@ -818,7 +818,7 @@ def : InstAlias<".insn_cr $opcode, $funct4, $rd, $rs2",
|
||||
(InsnCR AnyReg:$rd, uimm2_opcode:$opcode, uimm4:$funct4,
|
||||
AnyReg:$rs2)>;
|
||||
def : InstAlias<".insn_ci $opcode, $funct3, $rd, $imm6",
|
||||
(InsnCI AnyRegC:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
|
||||
(InsnCI AnyReg:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
|
||||
simm6:$imm6)>;
|
||||
def : InstAlias<".insn_ciw $opcode, $funct3, $rd, $imm8",
|
||||
(InsnCIW AnyRegC:$rd, uimm2_opcode:$opcode, uimm3:$funct3,
|
||||
|
||||
@@ -1312,7 +1312,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
||||
|
||||
/// Implementation of algorithm to generate the compact unwind encoding
|
||||
/// for the CFI instructions.
|
||||
uint32_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
uint64_t generateCompactUnwindEncoding(const MCDwarfFrameInfo *FI,
|
||||
const MCContext *Ctxt) const override {
|
||||
ArrayRef<MCCFIInstruction> Instrs = FI->Instructions;
|
||||
if (Instrs.empty()) return 0;
|
||||
@@ -1327,13 +1327,13 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
||||
bool HasFP = false;
|
||||
|
||||
// Encode that we are using EBP/RBP as the frame pointer.
|
||||
uint32_t CompactUnwindEncoding = 0;
|
||||
uint64_t CompactUnwindEncoding = 0;
|
||||
|
||||
unsigned SubtractInstrIdx = Is64Bit ? 3 : 2;
|
||||
unsigned InstrOffset = 0;
|
||||
unsigned StackAdjust = 0;
|
||||
unsigned StackSize = 0;
|
||||
int MinAbsOffset = std::numeric_limits<int>::max();
|
||||
uint64_t StackSize = 0;
|
||||
int64_t MinAbsOffset = std::numeric_limits<int64_t>::max();
|
||||
|
||||
for (const MCCFIInstruction &Inst : Instrs) {
|
||||
switch (Inst.getOperation()) {
|
||||
@@ -1360,7 +1360,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
||||
memset(SavedRegs, 0, sizeof(SavedRegs));
|
||||
StackAdjust = 0;
|
||||
SavedRegIdx = 0;
|
||||
MinAbsOffset = std::numeric_limits<int>::max();
|
||||
MinAbsOffset = std::numeric_limits<int64_t>::max();
|
||||
InstrOffset += MoveInstrSize;
|
||||
break;
|
||||
}
|
||||
@@ -1403,7 +1403,7 @@ class DarwinX86AsmBackend : public X86AsmBackend {
|
||||
unsigned Reg = *MRI.getLLVMRegNum(Inst.getRegister(), true);
|
||||
SavedRegs[SavedRegIdx++] = Reg;
|
||||
StackAdjust += OffsetSize;
|
||||
MinAbsOffset = std::min(MinAbsOffset, abs(Inst.getOffset()));
|
||||
MinAbsOffset = std::min(MinAbsOffset, std::abs(Inst.getOffset()));
|
||||
InstrOffset += PushInstrSize(Reg);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -473,7 +473,7 @@ void X86FrameLowering::emitCalleeSavedFrameMovesFullCFA(
|
||||
: FramePtr;
|
||||
unsigned DwarfReg = MRI->getDwarfRegNum(MachineFramePtr, true);
|
||||
// Offset = space for return address + size of the frame pointer itself.
|
||||
unsigned Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4);
|
||||
int64_t Offset = (Is64Bit ? 8 : 4) + (Uses64BitFramePtr ? 8 : 4);
|
||||
BuildCFI(MBB, MBBI, DebugLoc{},
|
||||
MCCFIInstruction::createOffset(nullptr, DwarfReg, -Offset));
|
||||
emitCalleeSavedFrameMoves(MBB, MBBI, DebugLoc{}, true);
|
||||
@@ -2553,7 +2553,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
|
||||
if (!HasFP && NeedsDwarfCFI) {
|
||||
MBBI = FirstCSPop;
|
||||
int64_t Offset = -CSSize - SlotSize;
|
||||
int64_t Offset = -(int64_t)CSSize - SlotSize;
|
||||
// Mark callee-saved pop instruction.
|
||||
// Define the current CFA rule to use the provided offset.
|
||||
while (MBBI != MBB.end()) {
|
||||
|
||||
@@ -150,6 +150,7 @@ StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) {
|
||||
.Case("POWER8NVL", "pwr8")
|
||||
.Case("POWER9", "pwr9")
|
||||
.Case("POWER10", "pwr10")
|
||||
.Case("POWER11", "pwr11")
|
||||
// FIXME: If we get a simulator or machine with the capabilities of
|
||||
// mcpu=future, we should revisit this and add the name reported by the
|
||||
// simulator/machine.
|
||||
@@ -1549,6 +1550,12 @@ StringRef sys::getHostCPUName() {
|
||||
case 0x40000:
|
||||
#endif
|
||||
return "pwr10";
|
||||
#ifdef POWER_11
|
||||
case POWER_11:
|
||||
#else
|
||||
case 0x80000:
|
||||
#endif
|
||||
return "pwr11";
|
||||
default:
|
||||
return "generic";
|
||||
}
|
||||
|
||||
@@ -113,8 +113,6 @@ STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions "
|
||||
STATISTIC(NumIntAssociationsHoisted,
|
||||
"Number of invariant int expressions "
|
||||
"reassociated and hoisted out of the loop");
|
||||
STATISTIC(NumBOAssociationsHoisted, "Number of invariant BinaryOp expressions "
|
||||
"reassociated and hoisted out of the loop");
|
||||
|
||||
/// Memory promotion is enabled by default.
|
||||
static cl::opt<bool>
|
||||
@@ -2781,60 +2779,6 @@ static bool hoistMulAddAssociation(Instruction &I, Loop &L,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Reassociate general associative binary expressions of the form
|
||||
///
|
||||
/// 1. "(LV op C1) op C2" ==> "LV op (C1 op C2)"
|
||||
///
|
||||
/// where op is an associative binary op, LV is a loop variant, and C1 and C2
|
||||
/// are loop invariants that we want to hoist.
|
||||
///
|
||||
/// TODO: This can be extended to more cases such as
|
||||
/// 2. "C1 op (C2 op LV)" ==> "(C1 op C2) op LV"
|
||||
/// 3. "(C1 op LV) op C2" ==> "LV op (C1 op C2)" if op is commutative
|
||||
/// 4. "C1 op (LV op C2)" ==> "(C1 op C2) op LV" if op is commutative
|
||||
static bool hoistBOAssociation(Instruction &I, Loop &L,
|
||||
ICFLoopSafetyInfo &SafetyInfo,
|
||||
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
|
||||
DominatorTree *DT) {
|
||||
BinaryOperator *BO = dyn_cast<BinaryOperator>(&I);
|
||||
if (!BO || !BO->isAssociative())
|
||||
return false;
|
||||
|
||||
Instruction::BinaryOps Opcode = BO->getOpcode();
|
||||
BinaryOperator *Op0 = dyn_cast<BinaryOperator>(BO->getOperand(0));
|
||||
|
||||
// Transform: "(LV op C1) op C2" ==> "LV op (C1 op C2)"
|
||||
if (Op0 && Op0->getOpcode() == Opcode) {
|
||||
Value *LV = Op0->getOperand(0);
|
||||
Value *C1 = Op0->getOperand(1);
|
||||
Value *C2 = BO->getOperand(1);
|
||||
|
||||
if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) ||
|
||||
!L.isLoopInvariant(C2))
|
||||
return false;
|
||||
|
||||
auto *Preheader = L.getLoopPreheader();
|
||||
assert(Preheader && "Loop is not in simplify form?");
|
||||
IRBuilder<> Builder(Preheader->getTerminator());
|
||||
Value *Inv = Builder.CreateBinOp(Opcode, C1, C2, "invariant.op");
|
||||
|
||||
auto *NewBO =
|
||||
BinaryOperator::Create(Opcode, LV, Inv, BO->getName() + ".reass", BO);
|
||||
NewBO->copyIRFlags(BO);
|
||||
BO->replaceAllUsesWith(NewBO);
|
||||
eraseInstruction(*BO, SafetyInfo, MSSAU);
|
||||
|
||||
// Note: (LV op C1) might not be erased if it has more uses than the one we
|
||||
// just replaced.
|
||||
if (Op0->use_empty())
|
||||
eraseInstruction(*Op0, SafetyInfo, MSSAU);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool hoistArithmetics(Instruction &I, Loop &L,
|
||||
ICFLoopSafetyInfo &SafetyInfo,
|
||||
MemorySSAUpdater &MSSAU, AssumptionCache *AC,
|
||||
@@ -2872,12 +2816,6 @@ static bool hoistArithmetics(Instruction &I, Loop &L,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hoistBOAssociation(I, L, SafetyInfo, MSSAU, AC, DT)) {
|
||||
++NumHoisted;
|
||||
++NumBOAssociationsHoisted;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -946,13 +946,15 @@ static Immediate ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) {
|
||||
// FIXME: AR->getNoWrapFlags(SCEV::FlagNW)
|
||||
SCEV::FlagAnyWrap);
|
||||
return Result;
|
||||
} else if (EnableVScaleImmediates)
|
||||
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S))
|
||||
} else if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S)) {
|
||||
if (EnableVScaleImmediates && M->getNumOperands() == 2) {
|
||||
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(M->getOperand(0)))
|
||||
if (isa<SCEVVScale>(M->getOperand(1))) {
|
||||
S = SE.getConstant(M->getType(), 0);
|
||||
return Immediate::getScalable(C->getValue()->getSExtValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
return Immediate::getZero();
|
||||
}
|
||||
|
||||
|
||||
@@ -206,7 +206,7 @@ static cl::opt<unsigned> VectorizeMemoryCheckThreshold(
|
||||
cl::desc("The maximum allowed number of runtime memory checks"));
|
||||
|
||||
static cl::opt<bool> UseLegacyCostModel(
|
||||
"vectorize-use-legacy-cost-model", cl::init(false), cl::Hidden,
|
||||
"vectorize-use-legacy-cost-model", cl::init(true), cl::Hidden,
|
||||
cl::desc("Use the legacy cost model instead of the VPlan-based cost model. "
|
||||
"This option will be removed in the future."));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user