Skip to content

Commit d4a2597

Browse files
authored
Implement a subset of builtin_cpu_supports() features (#82809)
The PR implements a subset of features of function __builtin_cpu_support() for AIX OS based on the information which AIX kernel runtime variable `_system_configuration` and function call `getsystemcfg()` of /usr/include/sys/systemcfg.h in AIX OS can provide. Following subset of features are supported in the PR "arch_3_00", "arch_3_1","booke","cellbe","darn","dfp","dscr" ,"ebb","efpsingle","efpdouble","fpu","htm","isel", "mma","mmu","pa6t","power4","power5","power5+","power6x","ppc32","ppc601","ppc64","ppcle","smt", "spe","tar","true_le","ucache","vsx"
1 parent 0558c7e commit d4a2597

File tree

10 files changed

+442
-62
lines changed

10 files changed

+442
-62
lines changed

clang/lib/Basic/Targets/PPC.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,19 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
901901
}
902902

903903
bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
904+
llvm::Triple Triple = getTriple();
905+
if (Triple.isOSAIX()) {
906+
#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP, \
907+
VALUE) \
908+
.Case(NAME, true)
909+
return llvm::StringSwitch<bool>(FeatureStr)
910+
#include "llvm/TargetParser/PPCTargetParser.def"
911+
.Default(false);
912+
}
913+
914+
assert(Triple.isOSLinux() &&
915+
"__builtin_cpu_supports() is only supported for AIX and Linux.");
916+
904917
#define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true)
905918
return llvm::StringSwitch<bool>(FeatureStr)
906919
#include "llvm/TargetParser/PPCTargetParser.def"
@@ -910,7 +923,7 @@ bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
910923
bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const {
911924
llvm::Triple Triple = getTriple();
912925
if (Triple.isOSAIX()) {
913-
#define PPC_AIX_CPU(NAME, SUPPORT, INDEX, OP, VALUE) .Case(NAME, true)
926+
#define PPC_AIX_CPU(NAME, SUPPORT_METHOD, INDEX, OP, VALUE) .Case(NAME, true)
914927
return llvm::StringSwitch<bool>(CPUName)
915928
#include "llvm/TargetParser/PPCTargetParser.def"
916929
.Default(false);

clang/lib/Basic/Targets/PPC.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,14 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
366366
// have Glibc since it is Glibc that provides the HWCAP[2] in the auxv.
367367
static constexpr int MINIMUM_AIX_OS_MAJOR = 7;
368368
static constexpr int MINIMUM_AIX_OS_MINOR = 2;
369-
bool supportsCpuSupports() const override { return getTriple().isOSGlibc(); }
369+
bool supportsCpuSupports() const override {
370+
llvm::Triple Triple = getTriple();
371+
// AIX 7.2 is the minimum requirement to support __builtin_cpu_supports().
372+
return Triple.isOSGlibc() ||
373+
(Triple.isOSAIX() &&
374+
!Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));
375+
}
376+
370377
bool supportsCpuIs() const override {
371378
llvm::Triple Triple = getTriple();
372379
// AIX 7.2 is the minimum requirement to support __builtin_cpu_is().

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16783,32 +16783,53 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1678316783

1678416784
#include "llvm/TargetParser/PPCTargetParser.def"
1678516785
auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
16786-
unsigned CompOp,
16786+
unsigned Mask, CmpInst::Predicate CompOp,
1678716787
unsigned OpValue) -> Value * {
1678816788
if (SupportMethod == AIX_BUILTIN_PPC_FALSE)
1678916789
return llvm::ConstantInt::getFalse(ConvertType(E->getType()));
1679016790

1679116791
if (SupportMethod == AIX_BUILTIN_PPC_TRUE)
1679216792
return llvm::ConstantInt::getTrue(ConvertType(E->getType()));
1679316793

16794-
assert(SupportMethod <= USE_SYS_CONF && "Invalid value for SupportMethod.");
16795-
assert((CompOp == COMP_EQ) && "Only equal comparisons are supported.");
16794+
assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod.");
16795+
16796+
llvm::Value *FieldValue = nullptr;
16797+
if (SupportMethod == USE_SYS_CONF) {
16798+
llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
16799+
llvm::Constant *SysConf =
16800+
CGM.CreateRuntimeVariable(STy, "_system_configuration");
16801+
16802+
// Grab the appropriate field from _system_configuration.
16803+
llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
16804+
ConstantInt::get(Int32Ty, FieldIdx)};
16805+
16806+
FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
16807+
FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
16808+
CharUnits::fromQuantity(4));
16809+
} else if (SupportMethod == SYS_CALL) {
16810+
llvm::FunctionType *FTy =
16811+
llvm::FunctionType::get(Int64Ty, Int32Ty, false);
16812+
llvm::FunctionCallee Func =
16813+
CGM.CreateRuntimeFunction(FTy, "getsystemcfg");
16814+
16815+
FieldValue =
16816+
Builder.CreateCall(Func, {ConstantInt::get(Int32Ty, FieldIdx)});
16817+
}
16818+
assert(FieldValue &&
16819+
"SupportMethod value is not defined in PPCTargetParser.def.");
1679616820

16797-
llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
16798-
llvm::Constant *SysConf =
16799-
CGM.CreateRuntimeVariable(STy, "_system_configuration");
16821+
if (Mask)
16822+
FieldValue = Builder.CreateAnd(FieldValue, Mask);
1680016823

16801-
// Grab the appropriate field from _system_configuration.
16802-
llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
16803-
ConstantInt::get(Int32Ty, FieldIdx)};
16824+
llvm::Type *ValueType = FieldValue->getType();
16825+
bool IsValueType64Bit = ValueType->isIntegerTy(64);
16826+
assert(
16827+
(IsValueType64Bit || ValueType->isIntegerTy(32)) &&
16828+
"Only 32/64-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
1680416829

16805-
llvm::Value *FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
16806-
FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
16807-
CharUnits::fromQuantity(4));
16808-
assert(FieldValue->getType()->isIntegerTy(32) &&
16809-
"Only 32-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
16810-
return Builder.CreateICmp(ICmpInst::ICMP_EQ, FieldValue,
16811-
ConstantInt::get(Int32Ty, OpValue));
16830+
return Builder.CreateICmp(
16831+
CompOp, FieldValue,
16832+
ConstantInt::get(IsValueType64Bit ? Int64Ty : Int32Ty, OpValue));
1681216833
};
1681316834

1681416835
switch (BuiltinID) {
@@ -16820,15 +16841,18 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1682016841
llvm::Triple Triple = getTarget().getTriple();
1682116842

1682216843
if (Triple.isOSAIX()) {
16823-
unsigned IsCpuSupport, FieldIdx, CompareOp, CpuIdValue;
16824-
typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUType;
16825-
std::tie(IsCpuSupport, FieldIdx, CompareOp, CpuIdValue) =
16844+
unsigned SupportMethod, FieldIdx, CpuIdValue;
16845+
CmpInst::Predicate CompareOp;
16846+
typedef std::tuple<unsigned, unsigned, CmpInst::Predicate, unsigned>
16847+
CPUType;
16848+
std::tie(SupportMethod, FieldIdx, CompareOp, CpuIdValue) =
1682616849
static_cast<CPUType>(StringSwitch<CPUType>(CPUStr)
16827-
#define PPC_AIX_CPU(NAME, SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE) \
16828-
.Case(NAME, {SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE})
16850+
#define PPC_AIX_CPU(NAME, SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE) \
16851+
.Case(NAME, {SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE})
1682916852
#include "llvm/TargetParser/PPCTargetParser.def"
16830-
);
16831-
return GenAIXPPCBuiltinCpuExpr(IsCpuSupport, FieldIdx, CompareOp,
16853+
.Default({AIX_BUILTIN_PPC_FALSE, 0,
16854+
CmpInst::Predicate(), 0}));
16855+
return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, 0, CompareOp,
1683216856
CpuIdValue);
1683316857
}
1683416858

@@ -16846,10 +16870,31 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1684616870
llvm::ConstantInt::get(Int32Ty, NumCPUID));
1684716871
}
1684816872
case Builtin::BI__builtin_cpu_supports: {
16849-
unsigned FeatureWord;
16850-
unsigned BitMask;
16873+
llvm::Triple Triple = getTarget().getTriple();
1685116874
const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
1685216875
StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
16876+
if (Triple.isOSAIX()) {
16877+
unsigned SupportMethod, FieldIdx, Mask, Value;
16878+
CmpInst::Predicate CompOp;
16879+
typedef std::tuple<unsigned, unsigned, unsigned, CmpInst::Predicate,
16880+
unsigned>
16881+
CPUSupportType;
16882+
std::tie(SupportMethod, FieldIdx, Mask, CompOp, Value) =
16883+
static_cast<CPUSupportType>(StringSwitch<CPUSupportType>(CPUStr)
16884+
#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP, \
16885+
VALUE) \
16886+
.Case(NAME, {SUPPORT_METHOD, INDEX, MASK, COMP_OP, VALUE})
16887+
#include "llvm/TargetParser/PPCTargetParser.def"
16888+
.Default({AIX_BUILTIN_PPC_FALSE, 0, 0,
16889+
CmpInst::Predicate(), 0}));
16890+
return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, Mask, CompOp,
16891+
Value);
16892+
}
16893+
16894+
assert(Triple.isOSLinux() &&
16895+
"__builtin_cpu_supports() is only supported for AIX and Linux.");
16896+
unsigned FeatureWord;
16897+
unsigned BitMask;
1685316898
std::tie(FeatureWord, BitMask) =
1685416899
StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
1685516900
#define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD) \

clang/lib/Sema/SemaChecking.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2346,10 +2346,8 @@ static bool BuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
23462346
if (!SupportsBI(&TI) && SupportsBI(AuxTI))
23472347
TheTI = AuxTI;
23482348

2349-
if (IsCPUSupports && !TheTI->supportsCpuSupports())
2350-
return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
2351-
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
2352-
if (!IsCPUSupports && !TheTI->supportsCpuIs())
2349+
if ((!IsCPUSupports && !TheTI->supportsCpuIs()) ||
2350+
(IsCPUSupports && !TheTI->supportsCpuSupports()))
23532351
return S.Diag(TheCall->getBeginLoc(),
23542352
TI.getTriple().isOSAIX()
23552353
? diag::err_builtin_aix_os_unsupported

clang/test/CodeGen/aix-builtin-cpu-is.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,12 @@
5757
// CHECK-NEXT: ret i32 0
5858
// CHECK-NEXT: }
5959

60-
// CHECKOP: @_system_configuration = external global { i32, i32, i32 }
60+
// CHECKOP: @_system_configuration = external global { i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64, i32, i32, i32, i32, i64, i64, i64, i64, i32, i32, i32, i32, i32, i32, i64, i32, i8, i8, i8, i8, i32, i32, i16, i16, [3 x i32], i32 }
6161
// CHECKOP: define i32 @main() #0 {
6262
// CHECKOP-NEXT: entry:
6363
// CHECKOP-NEXT: %retval = alloca i32, align 4
6464
// CHECKOP-NEXT: store i32 0, ptr %retval, align 4
65-
// CHECKOP-NEXT: %0 = load i32, ptr getelementptr inbounds ({ i32, i32, i32 }, ptr @_system_configuration, i32 0, i32 1), align 4
65+
// CHECKOP-NEXT: %0 = load i32, ptr getelementptr inbounds ({ i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i64, i32, i32, i32, i32, i64, i64, i64, i64, i32, i32, i32, i32, i32, i32, i64, i32, i8, i8, i8, i8, i32, i32, i16, i16, [3 x i32], i32 }, ptr @_system_configuration, i32 0, i32 1), align 4
6666
// CHECKOP-NEXT: %1 = icmp eq i32 %0, [[VALUE]]
6767
// CHECKOP-NEXT: %conv = zext i1 %1 to i32
6868
// CHECKOP-NEXT: ret i32 %conv

0 commit comments

Comments
 (0)