aboutsummaryrefslogtreecommitdiff
path: root/clang
diff options
context:
space:
mode:
authorzhijian lin <zhijian@ca.ibm.com>2024-02-22 08:46:08 -0500
committerGitHub <noreply@github.com>2024-02-22 08:46:08 -0500
commit5b8e5604c297aa8fd09bf641d12d0a663e0ea801 (patch)
treeb0b9d8be52c1fad3c1e2c6c761039eb4f59a1f6d /clang
parent770fd3856660fea6cbaa78d9cb1f03cc92611783 (diff)
downloadllvm-5b8e5604c297aa8fd09bf641d12d0a663e0ea801.zip
llvm-5b8e5604c297aa8fd09bf641d12d0a663e0ea801.tar.gz
llvm-5b8e5604c297aa8fd09bf641d12d0a663e0ea801.tar.bz2
[AIX] Lower intrinsic __builtin_cpu_is into AIX platform-specific code. (#80069)
On AIX OS, __builtin_cpu_is() references the runtime external variable _system_configuration from /usr/include/sys/systemcfg.h. ref issue: https://github.com/llvm/llvm-project/issues/80042
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/Basic/Targets/PPC.cpp10
-rw-r--r--clang/lib/Basic/Targets/PPC.h10
-rw-r--r--clang/lib/CodeGen/CGBuiltin.cpp47
-rw-r--r--clang/lib/Sema/SemaChecking.cpp5
-rw-r--r--clang/test/CodeGen/aix-builtin-cpu-is.c71
-rw-r--r--clang/test/Sema/aix-builtin-cpu-unsupports.c6
7 files changed, 149 insertions, 2 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1141188..a96f69d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10364,6 +10364,8 @@ def err_x86_builtin_tile_arg_duplicate : Error<
def err_builtin_target_unsupported : Error<
"builtin is not supported on this target">;
+def err_builtin_aix_os_unsupported : Error<
+ "this builtin is available only on AIX 7.2 and later operating systems">;
def err_builtin_longjmp_unsupported : Error<
"__builtin_longjmp is not supported for the current target">;
def err_builtin_setjmp_unsupported : Error<
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index 8c891cc..aebe51b 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -904,6 +904,16 @@ bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
}
bool PPCTargetInfo::validateCpuIs(StringRef CPUName) const {
+ llvm::Triple Triple = getTriple();
+ if (Triple.isOSAIX()) {
+#define PPC_AIX_CPU(NAME, SUPPORT, INDEX, OP, VALUE) .Case(NAME, true)
+ return llvm::StringSwitch<bool>(CPUName)
+#include "llvm/TargetParser/PPCTargetParser.def"
+ .Default(false);
+ }
+
+ assert(Triple.isOSLinux() &&
+ "__builtin_cpu_is() is only supported for AIX and Linux.");
#define PPC_LNX_CPU(NAME, NUM) .Case(NAME, true)
return llvm::StringSwitch<bool>(CPUName)
#include "llvm/TargetParser/PPCTargetParser.def"
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index a91bded..7068391 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -362,8 +362,16 @@ public:
// We support __builtin_cpu_supports/__builtin_cpu_is on targets that
// have Glibc since it is Glibc that provides the HWCAP[2] in the auxv.
+ static constexpr int MINIMUM_AIX_OS_MAJOR = 7;
+ static constexpr int MINIMUM_AIX_OS_MINOR = 2;
bool supportsCpuSupports() const override { return getTriple().isOSGlibc(); }
- bool supportsCpuIs() const override { return getTriple().isOSGlibc(); }
+ bool supportsCpuIs() const override {
+ llvm::Triple Triple = getTriple();
+ // AIX 7.2 is the minimum requirement to support __builtin_cpu_is().
+ return Triple.isOSGlibc() ||
+ (Triple.isOSAIX() &&
+ !Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));
+ }
bool validateCpuSupports(StringRef Feature) const override;
bool validateCpuIs(StringRef Name) const override;
};
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index d454ccc..d8b2115 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -16542,12 +16542,59 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
Intrinsic::ID ID = Intrinsic::not_intrinsic;
+#include "llvm/TargetParser/PPCTargetParser.def"
+ auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
+ unsigned CompOp,
+ unsigned OpValue) -> Value * {
+ if (SupportMethod == AIX_BUILTIN_PPC_FALSE)
+ return llvm::ConstantInt::getFalse(ConvertType(E->getType()));
+
+ if (SupportMethod == AIX_BUILTIN_PPC_TRUE)
+ return llvm::ConstantInt::getTrue(ConvertType(E->getType()));
+
+ assert(SupportMethod <= USE_SYS_CONF && "Invalid value for SupportMethod.");
+ assert((CompOp == COMP_EQ) && "Only equal comparisons are supported.");
+
+ llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
+ llvm::Constant *SysConf =
+ CGM.CreateRuntimeVariable(STy, "_system_configuration");
+
+ // Grab the appropriate field from _system_configuration.
+ llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
+ ConstantInt::get(Int32Ty, FieldIdx)};
+
+ llvm::Value *FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
+ FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
+ CharUnits::fromQuantity(4));
+ assert(FieldValue->getType()->isIntegerTy(32) &&
+ "Only 32-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
+ return Builder.CreateICmp(ICmpInst::ICMP_EQ, FieldValue,
+ ConstantInt::get(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();
+ llvm::Triple Triple = getTarget().getTriple();
+
+ if (Triple.isOSAIX()) {
+ unsigned IsCpuSupport, FieldIdx, CompareOp, CpuIdValue;
+ typedef std::tuple<unsigned, unsigned, unsigned, unsigned> CPUType;
+ std::tie(IsCpuSupport, FieldIdx, CompareOp, CpuIdValue) =
+ static_cast<CPUType>(StringSwitch<CPUType>(CPUStr)
+#define PPC_AIX_CPU(NAME, SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE) \
+ .Case(NAME, {SUPPORT_MAGIC, INDEX, COMPARE_OP, VALUE})
+#include "llvm/TargetParser/PPCTargetParser.def"
+ );
+ return GenAIXPPCBuiltinCpuExpr(IsCpuSupport, FieldIdx, CompareOp,
+ CpuIdValue);
+ }
+
+ assert(Triple.isOSLinux() &&
+ "__builtin_cpu_is() is only supported for AIX and Linux.");
unsigned NumCPUID = StringSwitch<unsigned>(CPUStr)
#define PPC_LNX_CPU(Name, NumericID) .Case(Name, NumericID)
#include "llvm/TargetParser/PPCTargetParser.def"
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e8bfb21..710437b 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2165,7 +2165,10 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
if (!IsCPUSupports && !TheTI->supportsCpuIs())
- return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
+ return S.Diag(TheCall->getBeginLoc(),
+ TI.getTriple().isOSAIX()
+ ? diag::err_builtin_aix_os_unsupported
+ : diag::err_builtin_target_unsupported)
<< SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
Expr *Arg = TheCall->getArg(0)->IgnoreParenImpCasts();
diff --git a/clang/test/CodeGen/aix-builtin-cpu-is.c b/clang/test/CodeGen/aix-builtin-cpu-is.c
new file mode 100644
index 0000000..b0a0dec4
--- /dev/null
+++ b/clang/test/CodeGen/aix-builtin-cpu-is.c
@@ -0,0 +1,71 @@
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc970\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc-cell-be\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppca2\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc405\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc440\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc464\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"ppc476\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power4\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power5\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power5+\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power6\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power6x\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power7\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DVALUE=32768 \
+// RUN: --check-prefix=CHECKOP
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power8\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DVALUE=65536 \
+// RUN: --check-prefix=CHECKOP
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power9\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DVALUE=131072\
+// RUN: --check-prefix=CHECKOP
+
+// RUN: echo "int main() { return __builtin_cpu_is(\"power10\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DVALUE=262144 \
+// RUN: --check-prefix=CHECKOP
+
+// CHECK: define i32 @main() #0 {
+// CHECK-NEXT: entry:
+// CHECK-NEXT: %retval = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr %retval, align 4
+// CHECK-NEXT: ret i32 0
+// CHECK-NEXT: }
+
+// CHECKOP: @_system_configuration = external global { i32, i32, i32 }
+// CHECKOP: define i32 @main() #0 {
+// CHECKOP-NEXT: entry:
+// CHECKOP-NEXT: %retval = alloca i32, align 4
+// CHECKOP-NEXT: store i32 0, ptr %retval, align 4
+// CHECKOP-NEXT: %0 = load i32, ptr getelementptr inbounds ({ i32, i32, i32 }, ptr @_system_configuration, i32 0, i32 1), align 4
+// CHECKOP-NEXT: %1 = icmp eq i32 %0, [[VALUE]]
+// CHECKOP-NEXT: %conv = zext i1 %1 to i32
+// CHECKOP-NEXT: ret i32 %conv
+// CHECKOP-NEXT: }
+
+
diff --git a/clang/test/Sema/aix-builtin-cpu-unsupports.c b/clang/test/Sema/aix-builtin-cpu-unsupports.c
new file mode 100644
index 0000000..10e21867
--- /dev/null
+++ b/clang/test/Sema/aix-builtin-cpu-unsupports.c
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -triple powerpc-ibm-aix7.1.0.0 -verify %s
+
+int main(void) {
+ if (__builtin_cpu_is("power8")) // expected-error {{this builtin is available only on AIX 7.2 and later operating systems}}
+ return 1;
+}