[llvm-branch-commits] [clang] [FMV][AIX] Implement target_clones (PR #177428)
Wael Yehia via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 22 20:49:27 PST 2026
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 <wyehia at ca.ibm.com>
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 <wyehia at ca.ibm.com>
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 <wyehia at ca.ibm.com>
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 <wyehia at ca.ibm.com>
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 <wyehia at ca.ibm.com>
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 at +1 {{unsupported 'fpmath=' in the 'target' attribute string; 'target' attribute ignored}}
int __attribute__((target("fpmath=387"))) walrus(void) { return 4; }
//expected-warning at +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 at +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 at +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 at +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 at +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 at +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 <wyehia at ca.ibm.com>
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;
More information about the llvm-branch-commits
mailing list