https://github.com/w2yehia updated https://github.com/llvm/llvm-project/pull/177428
>From f9ed73b88719aba0693e8a67fcf22fc866828478 Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Tue, 23 Sep 2025 14:22:57 -0400 Subject: [PATCH 1/6] refactor EmitPPCBuiltinCpu --- clang/lib/CodeGen/CodeGenFunction.h | 1 + clang/lib/CodeGen/TargetBuiltins/PPC.cpp | 62 +++++++++++++----------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 855e43631f436..2391ff76c05fe 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4869,6 +4869,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *BuildVector(ArrayRef<llvm::Value *> Ops); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitPPCBuiltinCpu(unsigned BuiltinID, llvm::Type *ReturnType, StringRef CPUStr); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp index 1e1127350c301..ea25ed691b454 100644 --- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp @@ -70,31 +70,18 @@ static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF, return CI; } -Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, - const CallExpr *E) { - // Do not emit the builtin arguments in the arguments of a function call, - // because the evaluation order of function arguments is not specified in C++. - // This is important when testing to ensure the arguments are emitted in the - // same order every time. Eg: - // Instead of: - // return Builder.CreateFDiv(EmitScalarExpr(E->getArg(0)), - // EmitScalarExpr(E->getArg(1)), "swdiv"); - // Use: - // Value *Op0 = EmitScalarExpr(E->getArg(0)); - // Value *Op1 = EmitScalarExpr(E->getArg(1)); - // return Builder.CreateFDiv(Op0, Op1, "swdiv") - - Intrinsic::ID ID = Intrinsic::not_intrinsic; +Value *CodeGenFunction::EmitPPCBuiltinCpu( + unsigned BuiltinID, llvm::Type *ReturnType, StringRef CPUStr) { #include "llvm/TargetParser/PPCTargetParser.def" auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx, unsigned Mask, CmpInst::Predicate CompOp, unsigned OpValue) -> Value * { if (SupportMethod == BUILTIN_PPC_FALSE) - return llvm::ConstantInt::getFalse(ConvertType(E->getType())); + return llvm::ConstantInt::getFalse(ReturnType); if (SupportMethod == BUILTIN_PPC_TRUE) - return llvm::ConstantInt::getTrue(ConvertType(E->getType())); + return llvm::ConstantInt::getTrue(ReturnType); assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod."); @@ -137,12 +124,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, ConstantInt::get(IsValueType64Bit ? Int64Ty : Int32Ty, OpValue)); }; - switch (BuiltinID) { - default: return nullptr; - - case Builtin::BI__builtin_cpu_is: { - const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); - StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + if (BuiltinID == Builtin::BI__builtin_cpu_is) { llvm::Triple Triple = getTarget().getTriple(); typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUInfo; @@ -170,7 +152,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, "Invalid CPU name. Missed by SemaChecking?"); if (LinuxSupportMethod == BUILTIN_PPC_FALSE) - return llvm::ConstantInt::getFalse(ConvertType(E->getType())); + return llvm::ConstantInt::getFalse(ReturnType); Value *Op0 = llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID); llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld); @@ -178,10 +160,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, return Builder.CreateICmpEQ(TheCall, llvm::ConstantInt::get(Int32Ty, LinuxIDValue)); } - case Builtin::BI__builtin_cpu_supports: { + else if (BuiltinID == Builtin::BI__builtin_cpu_supports) { llvm::Triple Triple = getTarget().getTriple(); - const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); - StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); if (Triple.isOSAIX()) { typedef std::tuple<unsigned, unsigned, unsigned, CmpInst::Predicate, unsigned> @@ -218,7 +198,35 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, #undef PPC_FAWORD_HWCAP2 #undef PPC_FAWORD_CPUID } + else + assert(0 && "unexpected builtin"); +} +Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + // Do not emit the builtin arguments in the arguments of a function call, + // because the evaluation order of function arguments is not specified in C++. + // This is important when testing to ensure the arguments are emitted in the + // same order every time. Eg: + // Instead of: + // return Builder.CreateFDiv(EmitScalarExpr(E->getArg(0)), + // EmitScalarExpr(E->getArg(1)), "swdiv"); + // Use: + // Value *Op0 = EmitScalarExpr(E->getArg(0)); + // Value *Op1 = EmitScalarExpr(E->getArg(1)); + // return Builder.CreateFDiv(Op0, Op1, "swdiv") + + Intrinsic::ID ID = Intrinsic::not_intrinsic; + + switch (BuiltinID) { + default: return nullptr; + + case Builtin::BI__builtin_cpu_is: + case Builtin::BI__builtin_cpu_supports: { + const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts(); + StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString(); + return EmitPPCBuiltinCpu(BuiltinID, ConvertType(E->getType()), CPUStr); + } // __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we // call __builtin_readcyclecounter. case PPC::BI__builtin_ppc_get_timebase: >From 6ec855bbb7744f4e618844ce9708dab2ce3ed528 Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Wed, 16 Jul 2025 20:02:11 +0000 Subject: [PATCH 2/6] clang codegen for target_clones --- clang/include/clang/Basic/TargetInfo.h | 2 +- clang/include/clang/Sema/SemaPPC.h | 4 ++ clang/lib/AST/ASTContext.cpp | 2 + clang/lib/Basic/Targets/PPC.cpp | 36 +++++++++++++ clang/lib/Basic/Targets/PPC.h | 4 ++ clang/lib/CodeGen/CodeGenFunction.cpp | 70 +++++++++++++++++++++++++- clang/lib/CodeGen/CodeGenFunction.h | 3 ++ clang/lib/CodeGen/CodeGenModule.cpp | 10 ++-- clang/lib/CodeGen/Targets/PPC.cpp | 47 +++++++++++++++++ clang/lib/Sema/SemaDeclAttr.cpp | 4 ++ clang/lib/Sema/SemaPPC.cpp | 56 +++++++++++++++++++++ 11 files changed, 231 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 89e1d7c99426f..0b07093e09fb5 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1564,7 +1564,7 @@ class TargetInfo : public TransferrableTargetInfo, /// which requires support for cpu_supports and cpu_is functionality. bool supportsMultiVersioning() const { return getTriple().isX86() || getTriple().isAArch64() || - getTriple().isRISCV(); + getTriple().isRISCV() || getTriple().isOSBinFormatXCOFF(); } /// Identify whether this target supports IFuncs. diff --git a/clang/include/clang/Sema/SemaPPC.h b/clang/include/clang/Sema/SemaPPC.h index f8edecc4fcb7b..0cf6ba7ff29dd 100644 --- a/clang/include/clang/Sema/SemaPPC.h +++ b/clang/include/clang/Sema/SemaPPC.h @@ -53,6 +53,10 @@ class SemaPPC : public SemaBase { // vector double vec_xxpermdi(vector double, vector double, int); // vector short vec_xxsldwi(vector short, vector short, int); bool BuiltinVSX(CallExpr *TheCall); + + bool checkTargetClonesAttr(SmallVectorImpl<StringRef> &Params, + SmallVectorImpl<SourceLocation> &Locs, + SmallVectorImpl<SmallString<64>> &NewParams); }; } // namespace clang diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f52470a4d7458..223f65ed1bf95 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -15021,6 +15021,8 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); + else if (Target->getTriple().isOSAIX() && VersionStr.starts_with("cpu=")) // TODO make a function that extracts CPU from a feature string + TargetCPU = VersionStr.drop_front(sizeof("cpu=") - 1); else if (VersionStr != "default") Features.push_back((StringRef{"+"} + VersionStr).str()); Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features); diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index a6e1ad10568bb..517e429ddfa1a 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -671,6 +671,42 @@ void PPCTargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features, } } +ParsedTargetAttr PPCTargetInfo::parseTargetAttr(StringRef Features) const { + ParsedTargetAttr Ret; + if (Features == "default") + return Ret; + SmallVector<StringRef, 1> AttrFeatures; + Features.split(AttrFeatures, ","); + + // Grab the various features and prepend a "+" to turn on the feature to + // the backend and add them to our existing set of features. + for (auto &Feature : AttrFeatures) { + // Go ahead and trim whitespace rather than either erroring or + // accepting it weirdly. + Feature = Feature.trim(); + + // While we're here iterating check for a different target cpu. + if (Feature.starts_with("cpu=")) { + assert(Ret.CPU.empty()); + Ret.CPU = Feature.split("=").second.trim(); + } else assert(0); +// else if (Feature.starts_with("tune=")) { +// if (!Ret.Tune.empty()) +// Ret.Duplicate = "tune="; +// else +// Ret.Tune = Feature.split("=").second.trim(); +// } else if (Feature.starts_with("no-")) +// Ret.Features.push_back("-" + Feature.split("-").second.str()); +// else +// Ret.Features.push_back("+" + Feature.str()); + } + return Ret; +} + +llvm::APInt PPCTargetInfo::getFMVPriority(ArrayRef<StringRef> Features) const { + return llvm::APInt(32, Features.empty() ? 0 : 1); +} + // Make sure that registers are added in the correct array index which should be // the DWARF number for PPC registers. const char *const PPCTargetInfo::GCCRegNames[] = { diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 664c9e15d8d18..6f90ff1f5d57c 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -199,6 +199,10 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo { bool supportsTargetAttributeTune() const override { return true; } + ParsedTargetAttr parseTargetAttr(StringRef Str) const override; + + llvm::APInt getFMVPriority(ArrayRef<StringRef> Features) const override; + ArrayRef<const char *> getGCCRegNames() const override; ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 02947c1df2c59..f52bd212a4170 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -44,6 +44,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/IntrinsicsPowerPC.h" #include "llvm/IR/MDBuilder.h" #include "llvm/Support/CRC.h" #include "llvm/Support/xxhash.h" @@ -3009,12 +3010,77 @@ void CodeGenFunction::EmitMultiVersionResolver( case llvm::Triple::riscv64: EmitRISCVMultiVersionResolver(Resolver, Options); return; - + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + if (getContext().getTargetInfo().getTriple().isOSAIX()) { + EmitPPCAIXMultiVersionResolver(Resolver, Options); + return; + } + [[fallthrough]]; default: - assert(false && "Only implemented for x86, AArch64 and RISC-V targets"); + assert(false && "Only implemented for x86, AArch64, RISC-V, and PowerPC targets"); + } +} + +/* + * Desc_t *foo_desc = ppc_get_function_descriptor(&foo); + * if (foo_desc->addr == ppc_get_function_entry(&foo)) { + * FuncPtr fp = resolver(); + * __c11_atomic_store((_Atomic FuncPtr *)&foo_desc->addr, fp, 0); + * } + * return ((int (*)(int)) foo_desc)(a); + */ +void CodeGenFunction::EmitPPCAIXMultiVersionResolver( + llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) { + + llvm::PointerType *PtrTy = Builder.getPtrTy(); + // entry: + llvm::BasicBlock *CurBlock = createBasicBlock("entry", Resolver); + + SmallVector<std::pair<llvm::Value *, llvm::BasicBlock *>, 3> PhiArgs; + for (const FMVResolverOption &RO : Options) { + Builder.SetInsertPoint(CurBlock); + // The 'default' or 'generic' case. + if (!RO.Architecture && RO.Features.empty()) { + // if.default: + // %fmv.default = call ptr @getEntryPoint(ptr noundef @foo_default) + // br label %resolver_exit + assert(&RO == Options.end() - 1 && "Default or Generic case must be last"); + Builder.CreateRet(RO.Function); + break; + } + // if.else_n: + // %is_version_n = __builtin_cpu_supports(version_n) + // br i1 %is_version_n, label %if.version_n, label %if.default + // + // if.version_n: + // %fmv.version.n = call ptr @getEntryPoint(ptr noundef @foo_version_n) + // br label %resolver_exit + assert(RO.Features.size() == 1 && "for now one feature requirement per version"); + llvm::Value *Condition; + if (RO.Features[0].starts_with("cpu=")) { + Condition = EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_is, Builder.getInt1Ty(), RO.Features[0].split("=").second.trim()); + } else { + Condition = EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_supports, Builder.getInt1Ty(), RO.Features[0]); + } + llvm::BasicBlock *ThenBlock = createBasicBlock("if.version", Resolver); + CurBlock = createBasicBlock("if.else", Resolver); + Builder.CreateCondBr(Condition, ThenBlock, CurBlock); + + Builder.SetInsertPoint(ThenBlock); + Builder.CreateRet(RO.Function); } + + // If no generic/default, emit an unreachable. +// Builder.SetInsertPoint(CurBlock); +// llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); +// TrapCall->setDoesNotReturn(); +// TrapCall->setDoesNotThrow(); +// Builder.CreateUnreachable(); +// Builder.ClearInsertionPoint(); } + void CodeGenFunction::EmitRISCVMultiVersionResolver( llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2391ff76c05fe..978dc2602a469 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5537,6 +5537,9 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitRISCVMultiVersionResolver(llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options); + void EmitPPCAIXMultiVersionResolver(llvm::Function *Resolver, + ArrayRef<FMVResolverOption> Options); + private: QualType getVarArgType(const Expr *Arg); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 85ed38f144627..4d9b000dfa52e 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2952,9 +2952,10 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, // While we populated the feature map above, we still need to // get and parse the target attribute so we can get the cpu for // the function. - if (TD) { - ParsedTargetAttr ParsedAttr = - Target.parseTargetAttr(TD->getFeaturesStr()); + StringRef FeatureStr = TD ? TD->getFeaturesStr() : + (TC ? TC->getFeatureStr(GD.getMultiVersionIndex()) : StringRef()); + if (!FeatureStr.empty()) { + ParsedTargetAttr ParsedAttr = Target.parseTargetAttr(FeatureStr); if (!ParsedAttr.CPU.empty() && getTarget().isValidCPUName(ParsedAttr.CPU)) { TargetCPU = ParsedAttr.CPU; @@ -4715,7 +4716,8 @@ void CodeGenModule::emitMultiVersionFunctions() { if (auto *IFunc = dyn_cast<llvm::GlobalIFunc>(ResolverConstant)) { ResolverConstant = IFunc->getResolver(); if (FD->isTargetClonesMultiVersion() && - !getTarget().getTriple().isAArch64()) { + !getTarget().getTriple().isAArch64() && + !getTarget().getTriple().isOSAIX()) { std::string MangledName = getMangledNameImpl( *this, GD, FD, /*OmitMultiVersionMangling=*/true); if (!GetGlobalValue(MangledName + ".ifunc")) { diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 35e7655646ade..bc357e0908a5e 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -128,8 +128,55 @@ class AIXABIInfo : public ABIInfo { RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty, AggValueSlot Slot) const override; + + using ABIInfo::appendAttributeMangling; + void appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index, + raw_ostream &Out) const override; + void appendAttributeMangling(StringRef AttrStr, + raw_ostream &Out) const override; }; +void AIXABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, + unsigned Index, + raw_ostream &Out) const { + appendAttributeMangling(Attr->getFeatureStr(Index), Out); +} + +void AIXABIInfo::appendAttributeMangling(StringRef AttrStr, + raw_ostream &Out) const { + if (AttrStr == "default") { + Out << ".default"; + return; + } + + Out << '.'; + const TargetInfo &TI = CGT.getTarget(); + ParsedTargetAttr Info = TI.parseTargetAttr(AttrStr); + + llvm::sort(Info.Features, [&TI](StringRef LHS, StringRef RHS) { + // Multiversioning doesn't allow "no-${feature}", so we can + // only have "+" prefixes here. + assert(LHS.starts_with("+") && RHS.starts_with("+") && + "Features should always have a prefix."); + return TI.getFMVPriority({LHS.substr(1)}) + .ugt(TI.getFMVPriority({RHS.substr(1)})); + }); + + bool IsFirst = true; + if (!Info.CPU.empty()) { + IsFirst = false; + Out << "cpu_" << Info.CPU; + } + + assert(Info.Features.empty() && "unhandled case"); + for (StringRef Feat : Info.Features) { + if (!IsFirst) + Out << '_'; + IsFirst = false; + Out << Feat.substr(1); + } +} + class AIXTargetCodeGenInfo : public TargetCodeGenInfo { const bool Is64Bit; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d762bcd789bf5..b309fcff1a6d1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -54,6 +54,7 @@ #include "clang/Sema/SemaObjC.h" #include "clang/Sema/SemaOpenCL.h" #include "clang/Sema/SemaOpenMP.h" +#include "clang/Sema/SemaPPC.h" #include "clang/Sema/SemaRISCV.h" #include "clang/Sema/SemaSYCL.h" #include "clang/Sema/SemaSwift.h" @@ -3521,6 +3522,9 @@ static void handleTargetClonesAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (S.X86().checkTargetClonesAttr(Params, Locations, NewParams, AL.getLoc())) return; + } else if (S.Context.getTargetInfo().getTriple().isOSAIX()) { + if (S.PPC().checkTargetClonesAttr(Params, Locations, NewParams)) + return; } Params.clear(); for (auto &SmallStr : NewParams) diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp index 536ba11088c8d..a6cf29c5c77ef 100644 --- a/clang/lib/Sema/SemaPPC.cpp +++ b/clang/lib/Sema/SemaPPC.cpp @@ -470,4 +470,60 @@ bool SemaPPC::BuiltinVSX(CallExpr *TheCall) { return false; } +bool SemaPPC::checkTargetClonesAttr( + SmallVectorImpl<StringRef> &Params, SmallVectorImpl<SourceLocation> &Locs, + SmallVectorImpl<SmallString<64>> &NewParams) { + using namespace DiagAttrParams; + + assert(Params.size() == Locs.size() && + "Mismatch between number of string parameters and locations"); + + bool HasDefault = false; + bool HasComma = false; + for (unsigned I = 0, E = Params.size(); I < E; ++I) { + const StringRef Param = Params[I].trim(); + const SourceLocation &Loc = Locs[I]; + + if (Param.empty() || Param.ends_with(',')) + return Diag(Loc, diag::warn_unsupported_target_attribute) + << Unsupported << None << "" << TargetClones; + + if (Param.contains(',')) + HasComma = true; + + StringRef LHS; + StringRef RHS = Param; + do { + std::tie(LHS, RHS) = RHS.split(','); + LHS = LHS.trim(); + const SourceLocation &CurLoc = + Loc.getLocWithOffset(LHS.data() - Param.data()); + + if (LHS.starts_with("cpu=")) { + if (!getASTContext().getTargetInfo().isValidCPUName( + LHS.drop_front(sizeof("cpu=") - 1))) + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << CPU << LHS.drop_front(sizeof("cpu=") - 1) + << TargetClones; + } else if (LHS == "default") + HasDefault = true; + else if (!getASTContext().getTargetInfo().isValidFeatureName(LHS) || + getASTContext().getTargetInfo().getFMVPriority(LHS) == 0) + return Diag(CurLoc, diag::warn_unsupported_target_attribute) + << Unsupported << None << LHS << TargetClones; + + if (llvm::is_contained(NewParams, LHS)) + Diag(CurLoc, diag::warn_target_clone_duplicate_options); + // Note: Add even if there are duplicates, since it changes name mangling. + NewParams.push_back(LHS); + } while (!RHS.empty()); + } + if (HasComma && Params.size() > 1) + Diag(Locs[0], diag::warn_target_clone_mixed_values); + + if (!HasDefault) + return Diag(Locs[0], diag::err_target_clone_must_have_default); + + return false; +} } // namespace clang >From ae54a3245ff9c41632be9d1b42d4b6d7b4fb128a Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Sat, 27 Sep 2025 23:26:33 -0400 Subject: [PATCH 3/6] ignore target_clones on a declaration and internalize the resolver and the clones --- clang/lib/CodeGen/CodeGenModule.cpp | 40 ++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 4d9b000dfa52e..2261efca7c8e2 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2043,6 +2043,19 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD, (CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage); } +// On certain platforms, a declared (but not defined) FMV shall be treated +// like a regular non-FMV function. +static bool IgnoreFMVOnADeclaration(const llvm::Triple &Triple, const FunctionDecl *FD) { + if (!FD->isMultiVersion()) + return false; + + if (Triple.isOSAIX()) { + assert(FD->isTargetClonesMultiVersion()); + return !FD->isDefined(); + } + return false; +} + static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, const NamedDecl *ND, bool OmitMultiVersionMangling = false) { @@ -2092,8 +2105,9 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, Out << CGM.getModuleNameHash(); } - if (const auto *FD = dyn_cast<FunctionDecl>(ND)) - if (FD->isMultiVersion() && !OmitMultiVersionMangling) { + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { + if (FD->isMultiVersion() && !OmitMultiVersionMangling && + !IgnoreFMVOnADeclaration(CGM.getTriple(), FD)) { switch (FD->getMultiVersionKind()) { case MultiVersionKind::CPUDispatch: case MultiVersionKind::CPUSpecific: @@ -2130,6 +2144,7 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, llvm_unreachable("None multiversion type isn't valid here"); } } + } // Make unique name for device side static file-scope variable for HIP. if (CGM.getContext().shouldExternalize(ND) && @@ -4630,7 +4645,8 @@ getFMVPriority(const TargetInfo &TI, static llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM, GlobalDecl GD) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - if (FD->getFormalLinkage() == Linkage::Internal) + if (FD->getFormalLinkage() == Linkage::Internal || + CGM.getTriple().isOSAIX()) return llvm::GlobalValue::InternalLinkage; return llvm::GlobalValue::WeakODRLinkage; } @@ -4664,7 +4680,7 @@ void CodeGenModule::emitMultiVersionFunctions() { // For AArch64, a resolver is only emitted if a function marked with // target_version("default")) or target_clones("default") is defined // in this TU. For other architectures it is always emitted. - bool ShouldEmitResolver = !getTarget().getTriple().isAArch64(); + bool ShouldEmitResolver = !getTriple().isAArch64(); SmallVector<CodeGenFunction::FMVResolverOption, 10> Options; llvm::DenseMap<llvm::Function *, const FunctionDecl *> DeclMap; @@ -4983,8 +4999,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { llvm::Constant *Resolver = GetOrCreateLLVMFunction( MangledName + ".resolver", ResolverType, GlobalDecl{}, /*ForVTable=*/false); + + auto Linkage = getTriple().isOSAIX() ? getFunctionLinkage(GD) : getMultiversionLinkage(*this, GD); + llvm::GlobalIFunc *GIF = - llvm::GlobalIFunc::create(DeclTy, AS, getMultiversionLinkage(*this, GD), + llvm::GlobalIFunc::create(DeclTy, AS, Linkage, "", Resolver, &getModule()); GIF->setName(ResolverName); SetCommonAttributes(FD, GIF); @@ -5004,7 +5023,9 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { void CodeGenModule::setMultiVersionResolverAttributes(llvm::Function *Resolver, GlobalDecl GD) { const NamedDecl *D = dyn_cast_or_null<NamedDecl>(GD.getDecl()); - Resolver->setLinkage(getMultiversionLinkage(*this, GD)); + + auto ResolverLinkage = getTriple().isOSAIX() ? llvm::GlobalValue::InternalLinkage : getMultiversionLinkage(*this, GD); + Resolver->setLinkage(ResolverLinkage); // Function body has to be emitted before calling setGlobalVisibility // for Resolver to be considered as definition. @@ -5083,6 +5104,10 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction( AddDeferredMultiVersionResolverToEmit(GD); NameWithoutMultiVersionMangling = getMangledNameImpl( *this, GD, FD, /*OmitMultiVersionMangling=*/true); + } else if (IgnoreFMVOnADeclaration(getTriple(), FD)) { + // TODO this might not be necessary after fix in getMangledNameImpl + NameWithoutMultiVersionMangling = getMangledNameImpl( + *this, GD, FD, /*OmitMultiVersionMangling=*/true); } else return GetOrCreateMultiVersionResolver(GD); } @@ -6543,6 +6568,9 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, auto *Fn = cast<llvm::Function>(GV); setFunctionLinkage(GD, Fn); + if (getTriple().isOSAIX() && D->isTargetClonesMultiVersion()) + Fn->setLinkage(llvm::GlobalValue::InternalLinkage); + // FIXME: this is redundant with part of setFunctionDefinitionAttributes setGVProperties(Fn, GD); >From de08e992b49822699b2505c16146b5c2829d09f4 Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Tue, 30 Sep 2025 15:27:07 -0400 Subject: [PATCH 4/6] fix PPCTargetInfo::parseTargetAttr --- clang/lib/Basic/Targets/PPC.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 517e429ddfa1a..8386291d002b3 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -687,18 +687,20 @@ ParsedTargetAttr PPCTargetInfo::parseTargetAttr(StringRef Features) const { // While we're here iterating check for a different target cpu. if (Feature.starts_with("cpu=")) { - assert(Ret.CPU.empty()); - Ret.CPU = Feature.split("=").second.trim(); - } else assert(0); -// else if (Feature.starts_with("tune=")) { -// if (!Ret.Tune.empty()) -// Ret.Duplicate = "tune="; -// else -// Ret.Tune = Feature.split("=").second.trim(); -// } else if (Feature.starts_with("no-")) -// Ret.Features.push_back("-" + Feature.split("-").second.str()); -// else -// Ret.Features.push_back("+" + Feature.str()); + if (!Ret.CPU.empty()) + Ret.Duplicate = "cpu="; + else + Ret.CPU = Feature.split("=").second.trim(); + } + else if (Feature.starts_with("tune=")) { + if (!Ret.Tune.empty()) + Ret.Duplicate = "tune="; + else + Ret.Tune = Feature.split("=").second.trim(); + } else if (Feature.starts_with("no-")) + Ret.Features.push_back("-" + Feature.split("-").second.str()); + else + Ret.Features.push_back("+" + Feature.str()); } return Ret; } >From 1ab4d6739d7280392710e5bcc540932b781029c3 Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Tue, 30 Sep 2025 19:38:35 +0000 Subject: [PATCH 5/6] fix Sema/attr-target.c --- clang/test/Sema/attr-target.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/clang/test/Sema/attr-target.c b/clang/test/Sema/attr-target.c index 65ece3c27d299..ddf6654632187 100644 --- a/clang/test/Sema/attr-target.c +++ b/clang/test/Sema/attr-target.c @@ -75,15 +75,13 @@ int __attribute__((target("tune=pwr8"))) baz(void) { return 4; } //expected-warning@+1 {{unsupported 'fpmath=' in the 'target' attribute string; 'target' attribute ignored}} int __attribute__((target("fpmath=387"))) walrus(void) { return 4; } //expected-warning@+1 {{unknown CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}} -int __attribute__((target("float128,arch=hiss"))) meow(void) { return 4; } +int __attribute__((target("float128,cpu=hiss"))) meow(void) { return 4; } // no warning, same as saying 'nothing'. -int __attribute__((target("arch="))) turtle(void) { return 4; } +int __attribute__((target("cpu="))) turtle(void) { return 4; } //expected-warning@+1 {{unknown CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}} -int __attribute__((target("arch=hiss,arch=woof"))) pine_tree(void) { return 4; } -//expected-warning@+1 {{duplicate 'arch=' in the 'target' attribute string; 'target' attribute ignored}} -int __attribute__((target("arch=pwr9,arch=pwr10"))) oak_tree(void) { return 4; } -//expected-warning@+1 {{unsupported 'branch-protection' in the 'target' attribute string; 'target' attribute ignored}} -int __attribute__((target("branch-protection=none"))) birch_tree(void) { return 5; } +int __attribute__((target("cpu=hiss,cpu=woof"))) pine_tree(void) { return 4; } +//expected-warning@+1 {{duplicate 'cpu=' in the 'target' attribute string; 'target' attribute ignored}} +int __attribute__((target("cpu=pwr9,cpu=pwr10"))) oak_tree(void) { return 4; } //expected-warning@+1 {{unknown tune CPU 'hiss' in the 'target' attribute string; 'target' attribute ignored}} int __attribute__((target("tune=hiss,tune=woof"))) apple_tree(void) { return 4; } >From c6358f5bbc77f7c9d35279832f08129b6988cf75 Mon Sep 17 00:00:00 2001 From: Wael Yehia <[email protected]> Date: Tue, 7 Oct 2025 23:11:21 +0000 Subject: [PATCH 6/6] clang-format --- clang/lib/AST/ASTContext.cpp | 5 +++- clang/lib/Basic/Targets/PPC.cpp | 3 +-- clang/lib/CodeGen/CodeGenFunction.cpp | 31 ++++++++++++++---------- clang/lib/CodeGen/CodeGenFunction.h | 5 ++-- clang/lib/CodeGen/CodeGenModule.cpp | 29 ++++++++++++---------- clang/lib/CodeGen/TargetBuiltins/PPC.cpp | 14 +++++------ clang/lib/CodeGen/Targets/PPC.cpp | 5 ++-- 7 files changed, 51 insertions(+), 41 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 223f65ed1bf95..65c8871ab5f0b 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -15021,7 +15021,10 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap, StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex()); if (VersionStr.starts_with("arch=")) TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1); - else if (Target->getTriple().isOSAIX() && VersionStr.starts_with("cpu=")) // TODO make a function that extracts CPU from a feature string + else if (Target->getTriple().isOSAIX() && + VersionStr.starts_with( + "cpu=")) // TODO make a function that extracts CPU from a + // feature string TargetCPU = VersionStr.drop_front(sizeof("cpu=") - 1); else if (VersionStr != "default") Features.push_back((StringRef{"+"} + VersionStr).str()); diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index 8386291d002b3..a6eb61fdc9907 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -691,8 +691,7 @@ ParsedTargetAttr PPCTargetInfo::parseTargetAttr(StringRef Features) const { Ret.Duplicate = "cpu="; else Ret.CPU = Feature.split("=").second.trim(); - } - else if (Feature.starts_with("tune=")) { + } else if (Feature.starts_with("tune=")) { if (!Ret.Tune.empty()) Ret.Duplicate = "tune="; else diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index f52bd212a4170..67f83f3db732c 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -3018,7 +3018,8 @@ void CodeGenFunction::EmitMultiVersionResolver( } [[fallthrough]]; default: - assert(false && "Only implemented for x86, AArch64, RISC-V, and PowerPC targets"); + assert(false && + "Only implemented for x86, AArch64, RISC-V, and PowerPC targets"); } } @@ -3031,7 +3032,7 @@ void CodeGenFunction::EmitMultiVersionResolver( * return ((int (*)(int)) foo_desc)(a); */ void CodeGenFunction::EmitPPCAIXMultiVersionResolver( - llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) { + llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) { llvm::PointerType *PtrTy = Builder.getPtrTy(); // entry: @@ -3045,7 +3046,8 @@ void CodeGenFunction::EmitPPCAIXMultiVersionResolver( // if.default: // %fmv.default = call ptr @getEntryPoint(ptr noundef @foo_default) // br label %resolver_exit - assert(&RO == Options.end() - 1 && "Default or Generic case must be last"); + assert(&RO == Options.end() - 1 && + "Default or Generic case must be last"); Builder.CreateRet(RO.Function); break; } @@ -3056,12 +3058,16 @@ void CodeGenFunction::EmitPPCAIXMultiVersionResolver( // if.version_n: // %fmv.version.n = call ptr @getEntryPoint(ptr noundef @foo_version_n) // br label %resolver_exit - assert(RO.Features.size() == 1 && "for now one feature requirement per version"); + assert(RO.Features.size() == 1 && + "for now one feature requirement per version"); llvm::Value *Condition; if (RO.Features[0].starts_with("cpu=")) { - Condition = EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_is, Builder.getInt1Ty(), RO.Features[0].split("=").second.trim()); + Condition = + EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_is, Builder.getInt1Ty(), + RO.Features[0].split("=").second.trim()); } else { - Condition = EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_supports, Builder.getInt1Ty(), RO.Features[0]); + Condition = EmitPPCBuiltinCpu(Builtin::BI__builtin_cpu_supports, + Builder.getInt1Ty(), RO.Features[0]); } llvm::BasicBlock *ThenBlock = createBasicBlock("if.version", Resolver); CurBlock = createBasicBlock("if.else", Resolver); @@ -3072,15 +3078,14 @@ void CodeGenFunction::EmitPPCAIXMultiVersionResolver( } // If no generic/default, emit an unreachable. -// Builder.SetInsertPoint(CurBlock); -// llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); -// TrapCall->setDoesNotReturn(); -// TrapCall->setDoesNotThrow(); -// Builder.CreateUnreachable(); -// Builder.ClearInsertionPoint(); + // Builder.SetInsertPoint(CurBlock); + // llvm::CallInst *TrapCall = EmitTrapCall(llvm::Intrinsic::trap); + // TrapCall->setDoesNotReturn(); + // TrapCall->setDoesNotThrow(); + // Builder.CreateUnreachable(); + // Builder.ClearInsertionPoint(); } - void CodeGenFunction::EmitRISCVMultiVersionResolver( llvm::Function *Resolver, ArrayRef<FMVResolverOption> Options) { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 978dc2602a469..9c38df935c9bc 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4869,7 +4869,8 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *BuildVector(ArrayRef<llvm::Value *> Ops); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *EmitPPCBuiltinCpu(unsigned BuiltinID, llvm::Type *ReturnType, StringRef CPUStr); + llvm::Value *EmitPPCBuiltinCpu(unsigned BuiltinID, llvm::Type *ReturnType, + StringRef CPUStr); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHLSLBuiltinExpr(unsigned BuiltinID, const CallExpr *E, @@ -5538,7 +5539,7 @@ class CodeGenFunction : public CodeGenTypeCache { ArrayRef<FMVResolverOption> Options); void EmitPPCAIXMultiVersionResolver(llvm::Function *Resolver, - ArrayRef<FMVResolverOption> Options); + ArrayRef<FMVResolverOption> Options); private: QualType getVarArgType(const Expr *Arg); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 2261efca7c8e2..35835e66bb2e6 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2045,7 +2045,8 @@ static bool isUniqueInternalLinkageDecl(GlobalDecl GD, // On certain platforms, a declared (but not defined) FMV shall be treated // like a regular non-FMV function. -static bool IgnoreFMVOnADeclaration(const llvm::Triple &Triple, const FunctionDecl *FD) { +static bool IgnoreFMVOnADeclaration(const llvm::Triple &Triple, + const FunctionDecl *FD) { if (!FD->isMultiVersion()) return false; @@ -2107,7 +2108,7 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD, if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { if (FD->isMultiVersion() && !OmitMultiVersionMangling && - !IgnoreFMVOnADeclaration(CGM.getTriple(), FD)) { + !IgnoreFMVOnADeclaration(CGM.getTriple(), FD)) { switch (FD->getMultiVersionKind()) { case MultiVersionKind::CPUDispatch: case MultiVersionKind::CPUSpecific: @@ -2967,8 +2968,9 @@ bool CodeGenModule::GetCPUAndFeaturesAttributes(GlobalDecl GD, // While we populated the feature map above, we still need to // get and parse the target attribute so we can get the cpu for // the function. - StringRef FeatureStr = TD ? TD->getFeaturesStr() : - (TC ? TC->getFeatureStr(GD.getMultiVersionIndex()) : StringRef()); + StringRef FeatureStr = + TD ? TD->getFeaturesStr() + : (TC ? TC->getFeatureStr(GD.getMultiVersionIndex()) : StringRef()); if (!FeatureStr.empty()) { ParsedTargetAttr ParsedAttr = Target.parseTargetAttr(FeatureStr); if (!ParsedAttr.CPU.empty() && @@ -4645,8 +4647,7 @@ getFMVPriority(const TargetInfo &TI, static llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM, GlobalDecl GD) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - if (FD->getFormalLinkage() == Linkage::Internal || - CGM.getTriple().isOSAIX()) + if (FD->getFormalLinkage() == Linkage::Internal || CGM.getTriple().isOSAIX()) return llvm::GlobalValue::InternalLinkage; return llvm::GlobalValue::WeakODRLinkage; } @@ -4733,7 +4734,7 @@ void CodeGenModule::emitMultiVersionFunctions() { ResolverConstant = IFunc->getResolver(); if (FD->isTargetClonesMultiVersion() && !getTarget().getTriple().isAArch64() && - !getTarget().getTriple().isOSAIX()) { + !getTarget().getTriple().isOSAIX()) { std::string MangledName = getMangledNameImpl( *this, GD, FD, /*OmitMultiVersionMangling=*/true); if (!GetGlobalValue(MangledName + ".ifunc")) { @@ -5000,11 +5001,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { MangledName + ".resolver", ResolverType, GlobalDecl{}, /*ForVTable=*/false); - auto Linkage = getTriple().isOSAIX() ? getFunctionLinkage(GD) : getMultiversionLinkage(*this, GD); + auto Linkage = getTriple().isOSAIX() ? getFunctionLinkage(GD) + : getMultiversionLinkage(*this, GD); - llvm::GlobalIFunc *GIF = - llvm::GlobalIFunc::create(DeclTy, AS, Linkage, - "", Resolver, &getModule()); + llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(DeclTy, AS, Linkage, "", + Resolver, &getModule()); GIF->setName(ResolverName); SetCommonAttributes(FD, GIF); if (ResolverGV) @@ -5024,7 +5025,9 @@ void CodeGenModule::setMultiVersionResolverAttributes(llvm::Function *Resolver, GlobalDecl GD) { const NamedDecl *D = dyn_cast_or_null<NamedDecl>(GD.getDecl()); - auto ResolverLinkage = getTriple().isOSAIX() ? llvm::GlobalValue::InternalLinkage : getMultiversionLinkage(*this, GD); + auto ResolverLinkage = getTriple().isOSAIX() + ? llvm::GlobalValue::InternalLinkage + : getMultiversionLinkage(*this, GD); Resolver->setLinkage(ResolverLinkage); // Function body has to be emitted before calling setGlobalVisibility @@ -6569,7 +6572,7 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD, setFunctionLinkage(GD, Fn); if (getTriple().isOSAIX() && D->isTargetClonesMultiVersion()) - Fn->setLinkage(llvm::GlobalValue::InternalLinkage); + Fn->setLinkage(llvm::GlobalValue::InternalLinkage); // FIXME: this is redundant with part of setFunctionDefinitionAttributes setGVProperties(Fn, GD); diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp index ea25ed691b454..881585cffe47b 100644 --- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp @@ -70,8 +70,9 @@ static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF, return CI; } -Value *CodeGenFunction::EmitPPCBuiltinCpu( - unsigned BuiltinID, llvm::Type *ReturnType, StringRef CPUStr) { +Value *CodeGenFunction::EmitPPCBuiltinCpu(unsigned BuiltinID, + llvm::Type *ReturnType, + StringRef CPUStr) { #include "llvm/TargetParser/PPCTargetParser.def" auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx, @@ -159,8 +160,7 @@ Value *CodeGenFunction::EmitPPCBuiltinCpu( Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is"); return Builder.CreateICmpEQ(TheCall, llvm::ConstantInt::get(Int32Ty, LinuxIDValue)); - } - else if (BuiltinID == Builtin::BI__builtin_cpu_supports) { + } else if (BuiltinID == Builtin::BI__builtin_cpu_supports) { llvm::Triple Triple = getTarget().getTriple(); if (Triple.isOSAIX()) { typedef std::tuple<unsigned, unsigned, unsigned, CmpInst::Predicate, @@ -197,8 +197,7 @@ Value *CodeGenFunction::EmitPPCBuiltinCpu( #undef PPC_FAWORD_HWCAP #undef PPC_FAWORD_HWCAP2 #undef PPC_FAWORD_CPUID - } - else + } else assert(0 && "unexpected builtin"); } @@ -219,7 +218,8 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Intrinsic::ID ID = Intrinsic::not_intrinsic; switch (BuiltinID) { - default: return nullptr; + default: + return nullptr; case Builtin::BI__builtin_cpu_is: case Builtin::BI__builtin_cpu_supports: { diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index bc357e0908a5e..61d110e3c7ae3 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -136,8 +136,7 @@ class AIXABIInfo : public ABIInfo { raw_ostream &Out) const override; }; -void AIXABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, - unsigned Index, +void AIXABIInfo::appendAttributeMangling(TargetClonesAttr *Attr, unsigned Index, raw_ostream &Out) const { appendAttributeMangling(Attr->getFeatureStr(Index), Out); } @@ -159,7 +158,7 @@ void AIXABIInfo::appendAttributeMangling(StringRef AttrStr, assert(LHS.starts_with("+") && RHS.starts_with("+") && "Features should always have a prefix."); return TI.getFMVPriority({LHS.substr(1)}) - .ugt(TI.getFMVPriority({RHS.substr(1)})); + .ugt(TI.getFMVPriority({RHS.substr(1)})); }); bool IsFirst = true; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
