Skip to content

Implement a subset of builtin_cpu_supports() features #82809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
May 2, 2024

Conversation

diggerlin
Copy link
Contributor

@diggerlin diggerlin commented Feb 23, 2024

The features which __builtin_cpu_support() supports are descripted in https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/PowerPC-Built-in-Functions.html#:~:text=The%20__builtin_cpu_supports%20function%20requires,in%20function%20is%20fully%20supported.

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.version of /usr/include/sys/systemcfg.h and getsystemcfg() can provide.

Following subset of feature are supports in the PR


"arch_3_00":  "CPU supports ISA 30"
"arch_3_1":  "CPU supports ISA 31"
"booke":  "CPU supports the Embedded ISA category"
"cellbe":  "CPU has a CELL broadband engine"
"darn":  "CPU supports the darn"
"dfp":  "CPU has a decimal floating point unit"
"dscr": "CPU supports the data stream control register"
"ebb": "CPU supports event base branching"
"efpsingle":  "CPU has a SPE single precision floating point unit"
"efpdouble":  "CPU has a SPE double precision floating point unit"
"fpu":  "CPU has a floating point unit"
"htm":  "CPU has hardware transaction memory instructions"
"isel":"CPU supports the integer select instruction"
"mma":  "CPU supports the matrix-multiply assist instructions"
"mmu":  "CPU has a memory management unit"
"pa6t":  "CPU supports the PA Semi 6T CORE ISA"
"power4":  "CPU supports ISA 200"
"power5":  "CPU supports ISA 202"
"power5+":  "CPU supports ISA 203"
"power6x":  "CPU supports ISA 205"
"ppc32":  "CPU supports 32-bit mode execution"
"ppc601":  "CPU supports the old POWER ISA"
"ppc64":  "CPU supports 64-bit mode execution"
"ppcle":  "CPU supports a little-endian mode that uses address swizzling"
"smt":  "CPU support simultaneous multi-threading"
"spe":  "CPU has a signal processing extension unit"
"tar": "CPU supports the target address register"
"true_le":  "CPU supports true little-endian mode"
"ucache":  "CPU has unified I/D cache"
"vsx":  "CPU supports the vector-scalar extension"

in the PR, __builtin_cpu_support("mma") being true indicate the CPU hardware support MMA, but user space application maybe can not use it if the MMA bit of PCR register is disable.

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:PowerPC clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen IR generation bugs: mangling, exceptions, etc. labels Feb 23, 2024
@llvmbot
Copy link
Member

llvmbot commented Feb 23, 2024

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-backend-powerpc

Author: zhijian lin (diggerlin)

Changes

The features which __builtin_cpu_support() supports are descripted in https://gcc.gnu.org/onlinedocs/gcc-8.1.0/gcc/PowerPC-Built-in-Functions.html#:~:text=The%20__builtin_cpu_supports%20function%20requires,in%20function%20is%20fully%20supported.

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.version of /usr/include/sys/systemcfg.h and getsystemcfg() can provide.


Patch is 28.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/82809.diff

9 Files Affected:

  • (modified) clang/lib/Basic/Targets/PPC.cpp (+12)
  • (modified) clang/lib/Basic/Targets/PPC.h (+8-1)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+77-22)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+2-4)
  • (modified) clang/test/CodeGen/aix-builtin-cpu-is.c (+2-2)
  • (added) clang/test/CodeGen/aix-builtin-cpu-supports.c (+154)
  • (modified) clang/test/Sema/aix-builtin-cpu-unsupports.c (+38-2)
  • (added) clang/test/Sema/builtin-cpu-unsupports-AIX-Os.c (+9)
  • (modified) llvm/include/llvm/TargetParser/PPCTargetParser.def (+67-6)
diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp
index aebe51bfa4daad..17b462c73bfc6a 100644
--- a/clang/lib/Basic/Targets/PPC.cpp
+++ b/clang/lib/Basic/Targets/PPC.cpp
@@ -897,6 +897,18 @@ ArrayRef<Builtin::Info> PPCTargetInfo::getTargetBuiltins() const {
 }
 
 bool PPCTargetInfo::validateCpuSupports(StringRef FeatureStr) const {
+  llvm::Triple Triple = getTriple();
+  if (Triple.isOSAIX()) {
+#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, OP, VALUE)    \
+  .Case(NAME, true)
+    return llvm::StringSwitch<bool>(FeatureStr)
+#include "llvm/TargetParser/PPCTargetParser.def"
+        .Default(false);
+  }
+
+  assert(Triple.isOSLinux() &&
+         "__builtin_cpu_supports() is only supported for AIX and Linux.");
+
 #define PPC_LNX_FEATURE(NAME, DESC, ENUMNAME, ENUMVAL, HWCAPN) .Case(NAME, true)
   return llvm::StringSwitch<bool>(FeatureStr)
 #include "llvm/TargetParser/PPCTargetParser.def"
diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h
index 70683916a8b04f..39b52d362f36b8 100644
--- a/clang/lib/Basic/Targets/PPC.h
+++ b/clang/lib/Basic/Targets/PPC.h
@@ -364,7 +364,14 @@ class LLVM_LIBRARY_VISIBILITY PPCTargetInfo : public TargetInfo {
   // 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 supportsCpuSupports() const override {
+    llvm::Triple Triple = getTriple();
+    // AIX 7.2 is the minimum requirement to support __builtin_cpu_supports().
+    return Triple.isOSGlibc() ||
+           (Triple.isOSAIX() &&
+            !Triple.isOSVersionLT(MINIMUM_AIX_OS_MAJOR, MINIMUM_AIX_OS_MINOR));
+  }
+
   bool supportsCpuIs() const override {
     llvm::Triple Triple = getTriple();
     // AIX 7.2 is the minimum requirement to support __builtin_cpu_is().
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 734eb5a035ca49..cf4ddc52ff362a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -16560,7 +16560,7 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
 
 #include "llvm/TargetParser/PPCTargetParser.def"
   auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
-                                     unsigned CompOp,
+                                     unsigned Mask, unsigned CompOp,
                                      unsigned OpValue) -> Value * {
     if (SupportMethod == AIX_BUILTIN_PPC_FALSE)
       return llvm::ConstantInt::getFalse(ConvertType(E->getType()));
@@ -16568,24 +16568,61 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
     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.");
+    assert(SupportMethod <= SYS_CALL && "Invalid value for SupportMethod.");
+
+    llvm::Value *FieldValue = nullptr;
+    if (SupportMethod == USE_SYS_CONF) {
+      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)};
+
+      FieldValue = Builder.CreateGEP(STy, SysConf, Idxs);
+      FieldValue = Builder.CreateAlignedLoad(Int32Ty, FieldValue,
+                                             CharUnits::fromQuantity(4));
+    } else if (SupportMethod == SYS_CALL) {
+      llvm::FunctionType *FTy =
+          llvm::FunctionType::get(Int64Ty, Int32Ty, false);
+      llvm::FunctionCallee Func =
+          CGM.CreateRuntimeFunction(FTy, "getsystemcfg");
+
+      FieldValue =
+          Builder.CreateCall(Func, {ConstantInt::get(Int32Ty, FieldIdx)});
+    }
+
+    if (Mask)
+      FieldValue = Builder.CreateAnd(FieldValue, Mask);
 
-    llvm::Type *STy = llvm::StructType::get(PPC_SYSTEMCONFIG_TYPE);
-    llvm::Constant *SysConf =
-        CGM.CreateRuntimeVariable(STy, "_system_configuration");
+    CmpInst::Predicate PreOp;
+    switch (CompOp) {
+    case COMP_EQ:
+      PreOp = ICmpInst::ICMP_EQ;
+      break;
+    case COMP_GT:
+      PreOp = ICmpInst::ICMP_UGT;
+      break;
+    case COMP_GE:
+      PreOp = ICmpInst::ICMP_UGE;
+      break;
+    case COMP_NE:
+      PreOp = ICmpInst::ICMP_NE;
+      break;
+    default:
+      llvm_unreachable("Compare type is not correct in PPCTargetParser.def.");
+    }
 
-    // Grab the appropriate field from _system_configuration.
-    llvm::Value *Idxs[] = {ConstantInt::get(Int32Ty, 0),
-                           ConstantInt::get(Int32Ty, FieldIdx)};
+    llvm::Type *ValueType = FieldValue->getType();
+    assert(
+        (ValueType->isIntegerTy(64) || ValueType->isIntegerTy(32)) &&
+        "Only 32/64-bit integers are supported in GenAIXPPCBuiltinCpuExpr().");
 
-    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));
+    return Builder.CreateICmp(
+        PreOp, FieldValue,
+        ConstantInt::get(ValueType->isIntegerTy(64) ? Int64Ty : Int32Ty,
+                         OpValue));
   };
 
   switch (BuiltinID) {
@@ -16597,15 +16634,15 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
     llvm::Triple Triple = getTarget().getTriple();
 
     if (Triple.isOSAIX()) {
-      unsigned IsCpuSupport, FieldIdx, CompareOp, CpuIdValue;
+      unsigned SupportMethod, 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})
+#define PPC_AIX_CPU(NAME, SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE)            \
+  .Case(NAME, {SUPPORT_METHOD, INDEX, COMPARE_OP, VALUE})
 #include "llvm/TargetParser/PPCTargetParser.def"
           );
-      return GenAIXPPCBuiltinCpuExpr(IsCpuSupport, FieldIdx, CompareOp,
+      return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, 0, CompareOp,
                                      CpuIdValue);
     }
 
@@ -16623,10 +16660,28 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
                                 llvm::ConstantInt::get(Int32Ty, NumCPUID));
   }
   case Builtin::BI__builtin_cpu_supports: {
-    unsigned FeatureWord;
-    unsigned BitMask;
+    llvm::Triple Triple = getTarget().getTriple();
     const Expr *CPUExpr = E->getArg(0)->IgnoreParenCasts();
     StringRef CPUStr = cast<clang::StringLiteral>(CPUExpr)->getString();
+    if (Triple.isOSAIX()) {
+      unsigned SupportMethod, FieldIdx, Mask, CompOp, Value;
+      typedef std::tuple<unsigned, unsigned, unsigned, unsigned, unsigned>
+          CPUSupportType;
+      std::tie(SupportMethod, FieldIdx, Mask, CompOp, Value) =
+          static_cast<CPUSupportType>(StringSwitch<CPUSupportType>(CPUStr)
+#define PPC_AIX_FEATURE(NAME, DESC, SUPPORT_METHOD, INDEX, MASK, COMP_OP,      \
+                        VALUE)                                                 \
+  .Case(NAME, {SUPPORT_METHOD, INDEX, MASK, COMP_OP, VALUE})
+#include "llvm/TargetParser/PPCTargetParser.def"
+          );
+      return GenAIXPPCBuiltinCpuExpr(SupportMethod, FieldIdx, Mask, CompOp,
+                                     Value);
+    }
+
+    assert(Triple.isOSLinux() &&
+           "__builtin_cpu_support() is only supported for AIX and Linux.");
+    unsigned FeatureWord;
+    unsigned BitMask;
     std::tie(FeatureWord, BitMask) =
         StringSwitch<std::pair<unsigned, unsigned>>(CPUStr)
 #define PPC_LNX_FEATURE(Name, Description, EnumName, Bitmask, FA_WORD)         \
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7fa295ebd94044..86175f1428b409 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2161,10 +2161,8 @@ static bool SemaBuiltinCpu(Sema &S, const TargetInfo &TI, CallExpr *TheCall,
   if (!SupportsBI(&TI) && SupportsBI(AuxTI))
     TheTI = AuxTI;
 
-  if (IsCPUSupports && !TheTI->supportsCpuSupports())
-    return S.Diag(TheCall->getBeginLoc(), diag::err_builtin_target_unsupported)
-           << SourceRange(TheCall->getBeginLoc(), TheCall->getEndLoc());
-  if (!IsCPUSupports && !TheTI->supportsCpuIs())
+  if ((!IsCPUSupports && !TheTI->supportsCpuIs()) ||
+      (IsCPUSupports && !TheTI->supportsCpuSupports()))
     return S.Diag(TheCall->getBeginLoc(),
                   TI.getTriple().isOSAIX()
                       ? diag::err_builtin_aix_os_unsupported
diff --git a/clang/test/CodeGen/aix-builtin-cpu-is.c b/clang/test/CodeGen/aix-builtin-cpu-is.c
index b0a0dec41b56c0..e17cf7353511a2 100644
--- a/clang/test/CodeGen/aix-builtin-cpu-is.c
+++ b/clang/test/CodeGen/aix-builtin-cpu-is.c
@@ -57,12 +57,12 @@
 // CHECK-NEXT:   ret i32 0
 // CHECK-NEXT: }
 
-// CHECKOP: @_system_configuration = external global { i32, i32, i32 }
+// 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 }
 // 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:   %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
 // CHECKOP-NEXT:   %1 = icmp eq i32 %0, [[VALUE]] 
 // CHECKOP-NEXT:  %conv = zext i1 %1 to i32
 // CHECKOP-NEXT:   ret i32 %conv
diff --git a/clang/test/CodeGen/aix-builtin-cpu-supports.c b/clang/test/CodeGen/aix-builtin-cpu-supports.c
new file mode 100644
index 00000000000000..638f3657e978c8
--- /dev/null
+++ b/clang/test/CodeGen/aix-builtin-cpu-supports.c
@@ -0,0 +1,154 @@
+// RUN: echo "int main() { return __builtin_cpu_supports(\"4xxmac\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"altivec\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=46 -DOP=ugt -DBIT=i32 -DVALUE=0 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"booke\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"cellbe\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"darn\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=uge -DBIT=i32 -DVALUE=262144 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"efpdouble\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"efpsingle\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"pa6t\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"fpu\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"htm\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=ugt -DLABLE=59  -DBIT=i64 -DVALUE=0 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,APICALL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"mma\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=ugt -DLABLE=62 -DBIT=i64 -DVALUE=0 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,APICALL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"mmu\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"arch_2_05\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"arch_2_06\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=uge -DBIT=i32 -DVALUE=32768 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"arch_2_07\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=uge -DBIT=i32 -DVALUE=65536 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"arch_3_00\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=uge -DBIT=i32 -DVALUE=131072 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"arch_3_1\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=1 -DOP=uge -DBIT=i32 -DVALUE=262144 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"dfp\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=53 -DOP=ne -DBIT=i32 -DVALUE=0 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"power4\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"power5\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"power5+\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"power6x\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"ppc32\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"ppc601\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"ppc64\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"ppcle\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"smt\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=44 -DMASK=3 -DOP=eq -DBIT=i32 -DVALUE=3 \
+// RUN:   --check-prefixes=CHECKOP,OPMASK,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"spe\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=0 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"true_le\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck -DBOOL=1 %s \
+// RUN:   --check-prefix=CHECKBOOL
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"ucache\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=5 -DMASK=2 -DOP=eq -DBIT=i32 -DVALUE=2 \
+// RUN:   --check-prefixes=CHECKOP,OPMASK,MEMVAR
+
+// RUN: echo "int main() { return __builtin_cpu_supports(\"vsx\");}" > %t.c
+// RUN: %clang_cc1 -triple powerpc-ibm-aix7.2.0.0 -emit-llvm -o - %t.c | FileCheck %s -DPOS=46 -DOP=ugt -DBIT=i32 -DVALUE=1 \
+// RUN:   --check-prefixes=CHECKOP,OPRT,MEMVAR
+
+// CHECKBOOL:     define i32 @main() #0 {
+// CHECKBOOL-NEXT: entry:
+// CHECKBOOL-NEXT:   %retval = alloca i32, align 4
+// CHECKBOOL-NEXT:   store i32 0, ptr %retval, align 4
+// CHECKBOOL-NEXT:   ret i32 [[BOOL]]
+// CHECKBOOL-NEXT: }
+
+// MEMVAR: @_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 }
+
+// CHECKOP:   define i32 @main() #0 {
+// CHECKOP-NEXT: entry:
+// CHECKOP-NEXT:   %retval = alloca i32, align 4
+// CHECKOP-NEXT:   store i32 0, ptr %retval, align 4
+
+// MEMVAR-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 [[POS]]), align 4
+// APICALL-NEXT:  %0 = call i64 @getsystemcfg(i32 [[LABLE]])
+
+// OPRT-NEXT:  %1 = icmp [[OP]] [[BIT]] %0, [[VALUE]]
+// OPRT-NEXT:     %conv = zext i1 %1 to i32
+
+// OPMASK-NEXT:  %1 = and i32 %0, [[MASK]]
+// OPMASK-NEXT:  %2 = icmp [[OP]] i32 %1, [[VALUE]]
+// OPMASK-NEXT:  %conv = zext i1 %2 to i32
+
+// CHECKOP-NEXT:   ret i32 %conv
+// CHECKOP-NEXT: }
+
+// APICALL: declare i64 @getsystemcfg(i32)
+
+
diff --git a/clang/test/Sema/aix-builtin-cpu-unsupports.c b/clang/test/Sema/aix-builtin-cpu-unsupports.c
index 10e21867c39373..39cf3aea747f6e 100644
--- a/clang/test/Sema/aix-builtin-cpu-unsupports.c
+++ b/clang/test/Sema/aix-builtin-cpu-unsupports.c
@@ -1,6 +1,42 @@
-// RUN: %clang_cc1 -fsyntax-only -triple  powerpc-ibm-aix7.1.0.0 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -triple powerpc-ibm-aix7.2.0.0 -verify %s
 
 int main(void) {
-  ...
[truncated]

// When the value of SUPPORT_METHOD is USE_SYS_CONF, the return value
// depends on the result of comparing the data member of
// _system_configuration specified by INDEX with a certain value.
// AIX_BUILTIN_PPC_FALSE, USE_SYS_CONF, API_CALL.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// AIX_BUILTIN_PPC_FALSE, USE_SYS_CONF, API_CALL.
// AIX_BUILTIN_PPC_FALSE, USE_SYS_CONF, or SYS_CALL.

I don't see an API_CALL unless I am missing something. Do we mean SYS_CALL?

@diggerlin diggerlin requested a review from amy-kwan February 27, 2024 16:54
Copy link
Contributor

@amy-kwan amy-kwan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Group review comments.

Comment on lines 140 to 141
#define SC_TM_VER 59
#define SC_MMA_VER 62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#define SC_TM_VER 59
#define SC_MMA_VER 62
#define SYC_CALL_TM_VER 59
#define SYS_CALL_MMA_VER 62

It would be more clear to expand what SC is, because it can mean either sys call or sys conf.

ConstantInt::get(Int32Ty, FieldIdx)};
llvm::Type *ValueType = FieldValue->getType();
assert(
(ValueType->isIntegerTy(64) || ValueType->isIntegerTy(32)) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can pull out ValueType->isIntegerTy(64) since we use it twice (here and below).

@diggerlin diggerlin requested a review from amy-kwan February 29, 2024 15:28
@diggerlin diggerlin force-pushed the digger/builtin_cpu_supports branch from ea3702e to 557e716 Compare March 5, 2024 19:20
@@ -16570,32 +16570,72 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,

#include "llvm/TargetParser/PPCTargetParser.def"
auto GenAIXPPCBuiltinCpuExpr = [&](unsigned SupportMethod, unsigned FieldIdx,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now a very large lambda function AFAICT. Please extract it into a static function to aid readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am prefer to keep as lambda

  1. after delete the switch case part, the size of lambda reduce.
  2. if I create static function , there will many parameter to for the static function, I need to add builder, Int32Ty, Int64Ty etc as parameter.

Comment on lines 155 to 158
#define COMP_EQ 0
#define COMP_GT 1
#define COMP_GE 2
#define COMP_NE 3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not omit this and use CmpInst::Predicate in the function-style macros (thereby eliminating the need for the switch statement that uses them as well)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good idea.

// _system_configuration at INDEX, where the data member is masked by Mask.
// When the SUPPORT_METHOD value is set to SYS_CALL, the return value depends
// on comparing a VALUE with the return value of calling `getsystemcfg`
// with the parameter INDEX, which is then masked by Mask.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And presumably:

// AIX_BUILTIN_PPC_TRUE and AIX_BUILTIN_PPC_FALSE are for features
// that are supported or unsupported on all systems respectively.

?

@@ -0,0 +1,171 @@
// RUN: echo "int main() { return __builtin_cpu_supports(\"4xxmac\");}" > %t.c
Copy link
Member

@nemanjai nemanjai Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an interesting way of testing, where we create each test on the fly. I am not against it if it works on all platforms (including Windows).
However, I would like to see one test case where we have multiple calls to the builtins, with multiple uses of each "support method" in the same compilation unit.

Copy link
Contributor Author

@diggerlin diggerlin Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have used the way of testing in clang/test/CodeGen/aix-builtin-cpu-is.c . I will add with multiple uses of each "support method" in the same compilation unit.

@diggerlin diggerlin requested a review from nemanjai March 6, 2024 21:55
@diggerlin diggerlin requested a review from amy-kwan March 18, 2024 17:47
FieldValue =
Builder.CreateCall(Func, {ConstantInt::get(Int32Ty, FieldIdx)});
}
assert((FieldValue != nullptr) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can probably just do assert(FieldValue && "SupportMethod value is not defined in PPCTargetParser.def.");?

@diggerlin diggerlin requested a review from amy-kwan March 19, 2024 20:23
Comment on lines 156 to 164
// AIX_BUILTIN_PPC_FALSE, USE_SYS_CONF, SYS_CALL.
// When the value of SUPPORT_METHOD is set to USE_SYS_CONF, the return value
// depends on comparing VALUE with the specified data member of
// _system_configuration at INDEX, where the data member is masked by Mask.
// When the SUPPORT_METHOD value is set to SYS_CALL, the return value depends
// on comparing a VALUE with the return value of calling `getsystemcfg`
// with the parameter INDEX, which is then masked by Mask.
// AIX_BUILTIN_PPC_TRUE and AIX_BUILTIN_PPC_FALSE are for features
// that are supported or unsupported on all systems respectively.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this will be more clear:

Suggested change
// AIX_BUILTIN_PPC_FALSE, USE_SYS_CONF, SYS_CALL.
// When the value of SUPPORT_METHOD is set to USE_SYS_CONF, the return value
// depends on comparing VALUE with the specified data member of
// _system_configuration at INDEX, where the data member is masked by Mask.
// When the SUPPORT_METHOD value is set to SYS_CALL, the return value depends
// on comparing a VALUE with the return value of calling `getsystemcfg`
// with the parameter INDEX, which is then masked by Mask.
// AIX_BUILTIN_PPC_TRUE and AIX_BUILTIN_PPC_FALSE are for features
// that are supported or unsupported on all systems respectively.
// The value of SUPPORT_METHOD can be:
// AIX_BUILTIN_PPC_TRUE : feature supported
// AIX_BUILTIN_PPC_FALSE : feature not supported
// USE_SYS_CONF : return value depends on comparing VALUE with the specified
// data member of _system_configuration at INDEX, where the
// data member is masked by Mask.
// SYS_CALL : return value depends on comparing a VALUE with the return value
// of calling `getsystemcfg` with the parameter INDEX, which is
// then masked by Mask.

ret += __builtin_cpu_supports("htm");
ret += __builtin_cpu_supports("cellbe");
ret += __builtin_cpu_supports("power4");
return ret;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be good to add a call that will directly return true, another call to syscfg and doc which is which within the src here.

@diggerlin diggerlin requested a review from lei137 April 23, 2024 20:33
Copy link
Contributor

@lei137 lei137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@amy-kwan amy-kwan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have any further comments. LGTM.

@diggerlin diggerlin merged commit d4a2597 into llvm:main May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:PowerPC clang:codegen IR generation bugs: mangling, exceptions, etc. clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants