Skip to content

Commit 65c84f2

Browse files
Nemanja Ivanovicnemanjai
authored andcommitted
[PowerPC][X86] Make cpu id builtins target independent and lower for PPC
Make __builtin_cpu_{init|supports|is} target independent and provide an opt-in query for targets that want to support it. Each target is still responsible for their specific lowering/code-gen. Also provide code-gen for PowerPC.
1 parent a7759fb commit 65c84f2

File tree

17 files changed

+458
-82
lines changed

17 files changed

+458
-82
lines changed

clang/include/clang/Basic/Builtins.td

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,26 @@ def RotateRight : BitInt8_16_32_64BuiltinsTemplate, Builtin {
727727
// FIXME: The builtins marked FunctionWithBuiltinPrefix below should be
728728
// merged with the library definitions. They are currently not because
729729
// the attributes are different.
730+
731+
// Builtins for checking CPU features based on the GCC builtins.
732+
def BuiltinCPUIs : Builtin {
733+
let Spellings = ["__builtin_cpu_is"];
734+
let Attributes = [NoThrow, Const];
735+
let Prototype = "bool(char const*)";
736+
}
737+
738+
def BuiltinCPUSupports : Builtin {
739+
let Spellings = ["__builtin_cpu_supports"];
740+
let Attributes = [NoThrow, Const];
741+
let Prototype = "bool(char const*)";
742+
}
743+
744+
def BuiltinCPUInit : Builtin {
745+
let Spellings = ["__builtin_cpu_init"];
746+
let Attributes = [NoThrow];
747+
let Prototype = "void()";
748+
}
749+
730750
def BuiltinCalloc : Builtin {
731751
let Spellings = ["__builtin_calloc"];
732752
let Attributes = [FunctionWithBuiltinPrefix, NoThrow];

clang/include/clang/Basic/BuiltinsX86.def

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626
# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
2727
#endif
2828

29-
// Miscellaneous builtin for checking x86 cpu features.
30-
// TODO: Make this somewhat generic so that other backends
31-
// can use it?
32-
BUILTIN(__builtin_cpu_init, "v", "n")
33-
BUILTIN(__builtin_cpu_supports, "bcC*", "nc")
34-
BUILTIN(__builtin_cpu_is, "bcC*", "nc")
35-
3629
// Undefined Values
3730
//
3831
TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "")

clang/include/clang/Basic/TargetInfo.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,6 +1432,12 @@ class TargetInfo : public TransferrableTargetInfo,
14321432
getTriple().isOSFreeBSD());
14331433
}
14341434

1435+
// Identify whether this target supports __builtin_cpu_supports and
1436+
// __builtin_cpu_is.
1437+
virtual bool supportsCpuSupports() const { return false; }
1438+
virtual bool supportsCpuIs() const { return false; }
1439+
virtual bool supportsCpuInit() const { return false; }
1440+
14351441
// Validate the contents of the __builtin_cpu_supports(const char*)
14361442
// argument.
14371443
virtual bool validateCpuSupports(StringRef Name) const { return false; }

clang/lib/Basic/Targets/PPC.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,3 +878,17 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
878878
return llvm::ArrayRef(BuiltinInfo,
879879
clang::PPC::LastTSBuiltin - Builtin::FirstTSBuiltin);
880880
}
881+
882+
bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
883+
#define PPC_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true)
884+
return llvm::StringSwitch<bool>(FeatureStr)
885+
#include "llvm/TargetParser/PPCTargetParser.def"
886+
.Default(false);
887+
}
888+
889+
bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const {
890+
#define PPC_CPU(NAME, NUM) .Case(NAME, true)
891+
return llvm::StringSwitch<bool>(CPUName)
892+
#include "llvm/TargetParser/PPCTargetParser.def"
893+
.Default(false);
894+
}

clang/lib/Basic/Targets/PPC.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,13 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
359359
bool isSPRegName(StringRef RegName) const override {
360360
return RegName.equals("r1") || RegName.equals("x1");
361361
}
362+
363+
// We support __builtin_cpu_supports/__builtin_cpu_is on targets that
364+
// have GLIBC since it is GLIBC that provides the HWCAP[2] in the auxv.
365+
bool supportsCpuSupports() const override { return getTriple().isOSGlibc(); }
366+
bool supportsCpuIs() const override { return getTriple().isOSGlibc(); }
367+
bool validateCpuSupports(StringRef Feature) const override;
368+
bool validateCpuIs(StringRef Name) const override;
362369
};
363370

364371
class LLVM_LIBRARY_VISIBILITY PPC32TargetInfo : public PPCTargetInfo {

clang/lib/Basic/Targets/X86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,10 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo {
220220
return RegName.equals("esp") || RegName.equals("rsp");
221221
}
222222

223+
bool supportsCpuSupports() const override { return true; }
224+
bool supportsCpuIs() const override { return true; }
225+
bool supportsCpuInit() const override { return true; }
226+
223227
bool validateCpuSupports(StringRef FeatureStr) const override;
224228

225229
bool validateCpuIs(StringRef FeatureStr) const override;

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14053,11 +14053,11 @@ CodeGenFunction::EmitAArch64CpuSupports(ArrayRef<StringRef> FeaturesStrs) {
1405314053

1405414054
Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
1405514055
const CallExpr *E) {
14056-
if (BuiltinID == X86::BI__builtin_cpu_is)
14056+
if (BuiltinID == Builtin::BI__builtin_cpu_is)
1405714057
return EmitX86CpuIs(E);
14058-
if (BuiltinID == X86::BI__builtin_cpu_supports)
14058+
if (BuiltinID == Builtin::BI__builtin_cpu_supports)
1405914059
return EmitX86CpuSupports(E);
14060-
if (BuiltinID == X86::BI__builtin_cpu_init)
14060+
if (BuiltinID == Builtin::BI__builtin_cpu_init)
1406114061
return EmitX86CpuInit();
1406214062

1406314063
// Handle MSVC intrinsics before argument evaluation to prevent double
@@ -16545,6 +16545,42 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1654516545
switch (BuiltinID) {
1654616546
default: return nullptr;
1654716547

16548+
case Builtin::BI__builtin_cpu_is: {
16549+
const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
16550+
StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
16551+
unsigned NumCPUID = StringSwitch<unsigned>(CPUStr)
16552+
#define PPC_CPU(Name, NumericID) .Case(Name, NumericID)
16553+
#include "llvm/TargetParser/PPCTargetParser.def"
16554+
.Default(-1U);
16555+
Value *Op0 =
16556+
llvm::ConstantInt::get(Int32Ty, PPC_FAWORD_CPUID);
16557+
llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);
16558+
Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_is");
16559+
return Builder.CreateICmpEQ(TheCall,
16560+
llvm::ConstantInt::get(Int32Ty, NumCPUID));
16561+
}
16562+
case Builtin::BI__builtin_cpu_supports: {
16563+
unsigned FeatureWord;
16564+
unsigned BitMask;
16565+
const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
16566+
StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
16567+
std::tie(FeatureWord, BitMask) =
16568+
StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
16569+
#define PPC_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \
16570+
.Case(Name, {FA_WORD, Bitmask})
16571+
#include "llvm/TargetParser/PPCTargetParser.def"
16572+
.Default({0, 0});
16573+
Value *Op0 = llvm::ConstantInt::get(Int32Ty, FeatureWord);
16574+
llvm::Function *F = CGM.getIntrinsic(Intrinsic::ppc_fixed_addr_ld);
16575+
Value *TheCall = Builder.CreateCall(F, {Op0}, "cpu_supports");
16576+
Value *Mask =
16577+
Builder.CreateAnd(TheCall, llvm::ConstantInt::get(Int32Ty, BitMask));
16578+
return Builder.CreateICmpNE(Mask, llvm::Constant::getNullValue(Int32Ty));
16579+
#undef PPC_FAWORD_HWCAP
16580+
#undef PPC_FAWORD_HWCAP2
16581+
#undef PPC_FAWORD_CPUID
16582+
}
16583+
1654816584
// __builtin_ppc_get_timebase is GCC 4.8+'s PowerPC-specific name for what we
1654916585
// call __builtin_readcyclecounter.
1655016586
case PPC::BI__builtin_ppc_get_timebase:

clang/lib/Sema/SemaChecking.cpp

Lines changed: 77 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,6 +2143,66 @@ static bool checkFPMathBuiltinElementType(Sema &S, SourceLocation Loc,
21432143
return false;
21442144
}
21452145

2146+
/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
2147+
/// This checks that the target supports __builtin_cpu_supports and
2148+
/// that the string argument is constant and valid.
2149+
static bool SemaBuiltinCpuSupports(Sema &S, const TargetInfo &TI,
2150+
const TargetInfo *AuxTI, CallExpr *TheCall) {
2151+
Expr *Arg = TheCall->getArg(0);
2152+
2153+
const TargetInfo *TheTI = nullptr;
2154+
if (TI.supportsCpuSupports())
2155+
TheTI = &TI;
2156+
else if (AuxTI && AuxTI->supportsCpuSupports())
2157+
TheTI = AuxTI;
2158+
else
2159+
return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
2160+
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
2161+
2162+
// Check if the argument is a string literal.
2163+
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
2164+
return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
2165+
<< Arg->getSourceRange();
2166+
2167+
// Check the contents of the string.
2168+
StringRef Feature =
2169+
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
2170+
if (!TheTI->validateCpuSupports(Feature))
2171+
return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports)
2172+
<< Arg->getSourceRange();
2173+
return false;
2174+
}
2175+
2176+
/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *).
2177+
/// This checks that the target supports __builtin_cpu_is and
2178+
/// that the string argument is constant and valid.
2179+
static bool SemaBuiltinCpuIs(Sema &S, const TargetInfo &TI,
2180+
const TargetInfo *AuxTI, CallExpr *TheCall) {
2181+
Expr *Arg = TheCall->getArg(0);
2182+
2183+
const TargetInfo *TheTI = nullptr;
2184+
if (TI.supportsCpuIs())
2185+
TheTI = &TI;
2186+
else if (AuxTI && AuxTI->supportsCpuIs())
2187+
TheTI = AuxTI;
2188+
else
2189+
return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
2190+
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
2191+
2192+
// Check if the argument is a string literal.
2193+
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
2194+
return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
2195+
<< Arg->getSourceRange();
2196+
2197+
// Check the contents of the string.
2198+
StringRef Feature =
2199+
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
2200+
if (!TheTI->validateCpuIs(Feature))
2201+
return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is)
2202+
<< Arg->getSourceRange();
2203+
return false;
2204+
}
2205+
21462206
ExprResult
21472207
Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
21482208
CallExpr *TheCall) {
@@ -2171,6 +2231,23 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
21712231

21722232
FPOptions FPO;
21732233
switch (BuiltinID) {
2234+
case Builtin::BI__builtin_cpu_supports:
2235+
if (SemaBuiltinCpuSupports(*this, Context.getTargetInfo(),
2236+
Context.getAuxTargetInfo(), TheCall))
2237+
return ExprError();
2238+
break;
2239+
case Builtin::BI__builtin_cpu_is:
2240+
if (SemaBuiltinCpuIs(*this, Context.getTargetInfo(),
2241+
Context.getAuxTargetInfo(), TheCall))
2242+
return ExprError();
2243+
break;
2244+
case Builtin::BI__builtin_cpu_init:
2245+
if (!Context.getTargetInfo().supportsCpuInit()) {
2246+
Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
2247+
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
2248+
return ExprError();
2249+
}
2250+
break;
21742251
case Builtin::BI__builtin___CFStringMakeConstantString:
21752252
// CFStringMakeConstantString is currently not implemented for GOFF (i.e.,
21762253
// on z/OS) and for XCOFF (i.e., on AIX). Emit unsupported
@@ -6256,47 +6333,6 @@ bool Sema::CheckNVPTXBuiltinFunctionCall(const TargetInfo &TI,
62566333
return false;
62576334
}
62586335

6259-
/// SemaBuiltinCpuSupports - Handle __builtin_cpu_supports(char *).
6260-
/// This checks that the target supports __builtin_cpu_supports and
6261-
/// that the string argument is constant and valid.
6262-
static bool SemaBuiltinCpuSupports(Sema &S, const TargetInfo &TI,
6263-
CallExpr *TheCall) {
6264-
Expr *Arg = TheCall->getArg(0);
6265-
6266-
// Check if the argument is a string literal.
6267-
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
6268-
return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
6269-
<< Arg->getSourceRange();
6270-
6271-
// Check the contents of the string.
6272-
StringRef Feature =
6273-
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
6274-
if (!TI.validateCpuSupports(Feature))
6275-
return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_supports)
6276-
<< Arg->getSourceRange();
6277-
return false;
6278-
}
6279-
6280-
/// SemaBuiltinCpuIs - Handle __builtin_cpu_is(char *).
6281-
/// This checks that the target supports __builtin_cpu_is and
6282-
/// that the string argument is constant and valid.
6283-
static bool SemaBuiltinCpuIs(Sema &S, const TargetInfo &TI, CallExpr *TheCall) {
6284-
Expr *Arg = TheCall->getArg(0);
6285-
6286-
// Check if the argument is a string literal.
6287-
if (!isa<StringLiteral>(Arg->IgnoreParenImpCasts()))
6288-
return S.Diag(TheCall->getBeginLoc(), diag::err_expr_not_string_literal)
6289-
<< Arg->getSourceRange();
6290-
6291-
// Check the contents of the string.
6292-
StringRef Feature =
6293-
cast<StringLiteral>(Arg->IgnoreParenImpCasts())->getString();
6294-
if (!TI.validateCpuIs(Feature))
6295-
return S.Diag(TheCall->getBeginLoc(), diag::err_invalid_cpu_is)
6296-
<< Arg->getSourceRange();
6297-
return false;
6298-
}
6299-
63006336
// Check if the rounding mode is legal.
63016337
bool Sema::CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall) {
63026338
// Indicates if this instruction has rounding control or just SAE.
@@ -6771,12 +6807,6 @@ static bool isX86_32Builtin(unsigned BuiltinID) {
67716807

67726808
bool Sema::CheckX86BuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
67736809
CallExpr *TheCall) {
6774-
if (BuiltinID == X86::BI__builtin_cpu_supports)
6775-
return SemaBuiltinCpuSupports(*this, TI, TheCall);
6776-
6777-
if (BuiltinID == X86::BI__builtin_cpu_is)
6778-
return SemaBuiltinCpuIs(*this, TI, TheCall);
6779-
67806810
// Check for 32-bit only builtins on a 64-bit target.
67816811
const llvm::Triple &TT = TI.getTriple();
67826812
if (TT.getArch() != llvm::Triple::x86 && isX86_32Builtin(BuiltinID))

0 commit comments

Comments
 (0)