Skip to content

[RISCV] Support new groupid/bitmask for cpu_model #101632

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 5 commits into from
Aug 8, 2024

Conversation

BeMg
Copy link
Contributor

@BeMg BeMg commented Aug 2, 2024

The spec can be found at riscv-non-isa/riscv-c-api-doc#74.

  1. Add the new extension GroupID/Bitmask with latest hwprobe key.
  2. Update the initRISCVFeature
  3. Update EmitRISCVCpuSupports due to not only group0 now.

@BeMg BeMg requested review from asb, preames, kito-cheng and topperc August 2, 2024 08:19
@llvmbot llvmbot added clang Clang issues not falling into any other category compiler-rt backend:RISC-V clang:codegen IR generation bugs: mangling, exceptions, etc. compiler-rt:builtins labels Aug 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 2, 2024

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-clang-codegen

Author: Piyou Chen (BeMg)

Changes
  1. Add the new extension GroupID/Bitmask with latest hwprobe key.
  2. Update the initRISCVFeature
  3. Update EmitRISCVCpuSupports due to not only group0 now.

Full diff: https://github.com/llvm/llvm-project/pull/101632.diff

5 Files Affected:

  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+2-1)
  • (modified) clang/test/CodeGen/builtin-cpu-supports.c (+36-14)
  • (modified) compiler-rt/lib/builtins/cpu_model/riscv.c (+49-1)
  • (modified) llvm/include/llvm/TargetParser/RISCVISAInfo.h (+5-1)
  • (modified) llvm/lib/TargetParser/RISCVISAInfo.cpp (+43-26)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 0c2ee446aa303..c903064b12cba 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -14391,9 +14391,10 @@ Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) {
   };
 
   int BitPos = RISCVISAInfo::getRISCVFeaturesBitPosition(FeatureStr);
+  int GroupID = RISCVISAInfo::getRISCVFeaturesGroupID(FeatureStr);
   assert(BitPos != -1 && "validation should have rejected this feature");
   Value *MaskV = Builder.getInt64(1ULL << BitPos);
-  Value *Bitset = Builder.CreateAnd(LoadFeatureBit(0), MaskV);
+  Value *Bitset = Builder.CreateAnd(LoadFeatureBit(GroupID), MaskV);
   return Builder.CreateICmpEQ(Bitset, MaskV);
 }
 
diff --git a/clang/test/CodeGen/builtin-cpu-supports.c b/clang/test/CodeGen/builtin-cpu-supports.c
index 92c407653e660..461e49d0fc7fa 100644
--- a/clang/test/CodeGen/builtin-cpu-supports.c
+++ b/clang/test/CodeGen/builtin-cpu-supports.c
@@ -270,20 +270,30 @@ int test_ppc(int a) {
 // CHECK-RV32-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [1 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
 // CHECK-RV32-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 2097152
 // CHECK-RV32-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 2097152
-// CHECK-RV32-NEXT:    br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_END:%.*]]
+// CHECK-RV32-NEXT:    br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
 // CHECK-RV32:       if.then3:
 // CHECK-RV32-NEXT:    store i32 11, ptr [[RETVAL]], align 4
 // CHECK-RV32-NEXT:    br label [[RETURN]]
+// CHECK-RV32:       if.else4:
+// CHECK-RV32-NEXT:    [[TMP9:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [1 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 1), align 8
+// CHECK-RV32-NEXT:    [[TMP10:%.*]] = and i64 [[TMP9]], 8
+// CHECK-RV32-NEXT:    [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 8
+// CHECK-RV32-NEXT:    br i1 [[TMP11]], label [[IF_THEN5:%.*]], label [[IF_END:%.*]]
+// CHECK-RV32:       if.then5:
+// CHECK-RV32-NEXT:    store i32 11, ptr [[RETVAL]], align 4
+// CHECK-RV32-NEXT:    br label [[RETURN]]
 // CHECK-RV32:       if.end:
-// CHECK-RV32-NEXT:    br label [[IF_END4:%.*]]
-// CHECK-RV32:       if.end4:
-// CHECK-RV32-NEXT:    br label [[IF_END5:%.*]]
-// CHECK-RV32:       if.end5:
+// CHECK-RV32-NEXT:    br label [[IF_END6:%.*]]
+// CHECK-RV32:       if.end6:
+// CHECK-RV32-NEXT:    br label [[IF_END7:%.*]]
+// CHECK-RV32:       if.end7:
+// CHECK-RV32-NEXT:    br label [[IF_END8:%.*]]
+// CHECK-RV32:       if.end8:
 // CHECK-RV32-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK-RV32-NEXT:    br label [[RETURN]]
 // CHECK-RV32:       return:
-// CHECK-RV32-NEXT:    [[TMP9:%.*]] = load i32, ptr [[RETVAL]], align 4
-// CHECK-RV32-NEXT:    ret i32 [[TMP9]]
+// CHECK-RV32-NEXT:    [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-RV32-NEXT:    ret i32 [[TMP12]]
 //
 // CHECK-RV64-LABEL: define dso_local signext i32 @test_riscv(
 // CHECK-RV64-SAME: i32 noundef signext [[A:%.*]]) #[[ATTR0:[0-9]+]] {
@@ -311,20 +321,30 @@ int test_ppc(int a) {
 // CHECK-RV64-NEXT:    [[TMP6:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [1 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 0), align 8
 // CHECK-RV64-NEXT:    [[TMP7:%.*]] = and i64 [[TMP6]], 2097152
 // CHECK-RV64-NEXT:    [[TMP8:%.*]] = icmp eq i64 [[TMP7]], 2097152
-// CHECK-RV64-NEXT:    br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_END:%.*]]
+// CHECK-RV64-NEXT:    br i1 [[TMP8]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]]
 // CHECK-RV64:       if.then3:
 // CHECK-RV64-NEXT:    store i32 11, ptr [[RETVAL]], align 4
 // CHECK-RV64-NEXT:    br label [[RETURN]]
+// CHECK-RV64:       if.else4:
+// CHECK-RV64-NEXT:    [[TMP9:%.*]] = load i64, ptr getelementptr inbounds ({ i32, [1 x i64] }, ptr @__riscv_feature_bits, i32 0, i32 1, i32 1), align 8
+// CHECK-RV64-NEXT:    [[TMP10:%.*]] = and i64 [[TMP9]], 8
+// CHECK-RV64-NEXT:    [[TMP11:%.*]] = icmp eq i64 [[TMP10]], 8
+// CHECK-RV64-NEXT:    br i1 [[TMP11]], label [[IF_THEN5:%.*]], label [[IF_END:%.*]]
+// CHECK-RV64:       if.then5:
+// CHECK-RV64-NEXT:    store i32 11, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    br label [[RETURN]]
 // CHECK-RV64:       if.end:
-// CHECK-RV64-NEXT:    br label [[IF_END4:%.*]]
-// CHECK-RV64:       if.end4:
-// CHECK-RV64-NEXT:    br label [[IF_END5:%.*]]
-// CHECK-RV64:       if.end5:
+// CHECK-RV64-NEXT:    br label [[IF_END6:%.*]]
+// CHECK-RV64:       if.end6:
+// CHECK-RV64-NEXT:    br label [[IF_END7:%.*]]
+// CHECK-RV64:       if.end7:
+// CHECK-RV64-NEXT:    br label [[IF_END8:%.*]]
+// CHECK-RV64:       if.end8:
 // CHECK-RV64-NEXT:    store i32 0, ptr [[RETVAL]], align 4
 // CHECK-RV64-NEXT:    br label [[RETURN]]
 // CHECK-RV64:       return:
-// CHECK-RV64-NEXT:    [[TMP9:%.*]] = load i32, ptr [[RETVAL]], align 4
-// CHECK-RV64-NEXT:    ret i32 [[TMP9]]
+// CHECK-RV64-NEXT:    [[TMP12:%.*]] = load i32, ptr [[RETVAL]], align 4
+// CHECK-RV64-NEXT:    ret i32 [[TMP12]]
 //
 int test_riscv(int a) {
   __builtin_cpu_init();
@@ -334,6 +354,8 @@ int test_riscv(int a) {
     return 7;
   else if (__builtin_cpu_supports("v"))
     return 11;
+  else if (__builtin_cpu_supports("zcb"))
+    return 11;
   return 0;
 }
 #endif
diff --git a/compiler-rt/lib/builtins/cpu_model/riscv.c b/compiler-rt/lib/builtins/cpu_model/riscv.c
index 92931fae64fbf..0c443025b74c6 100644
--- a/compiler-rt/lib/builtins/cpu_model/riscv.c
+++ b/compiler-rt/lib/builtins/cpu_model/riscv.c
@@ -8,7 +8,7 @@
 
 #include "cpu_model.h"
 
-#define RISCV_FEATURE_BITS_LENGTH 1
+#define RISCV_FEATURE_BITS_LENGTH 2
 struct {
   unsigned length;
   unsigned long long features[RISCV_FEATURE_BITS_LENGTH];
@@ -105,6 +105,30 @@ struct {
 #define ZVKSH_BITMASK (1ULL << 58)
 #define ZVKT_GROUPID 0
 #define ZVKT_BITMASK (1ULL << 59)
+#define ZVE32X_GROUPID 0
+#define ZVE32X_BITMASK (1ULL << 60)
+#define ZVE32F_GROUPID 0
+#define ZVE32F_BITMASK (1ULL << 61)
+#define ZVE64X_GROUPID 0
+#define ZVE64X_BITMASK (1ULL << 62)
+#define ZVE64F_GROUPID 0
+#define ZVE64F_BITMASK (1ULL << 63)
+#define ZVE64D_GROUPID 1
+#define ZVE64D_BITMASK (1ULL << 0)
+#define ZIMOP_GROUPID 1
+#define ZIMOP_BITMASK (1ULL << 1)
+#define ZCA_GROUPID 1
+#define ZCA_BITMASK (1ULL << 2)
+#define ZCB_GROUPID 1
+#define ZCB_BITMASK (1ULL << 3)
+#define ZCD_GROUPID 1
+#define ZCD_BITMASK (1ULL << 4)
+#define ZCF_GROUPID 1
+#define ZCF_BITMASK (1ULL << 5)
+#define ZCMOP_GROUPID 1
+#define ZCMOP_BITMASK (1ULL << 6)
+#define ZAWRS_GROUPID 1
+#define ZAWRS_BITMASK (1ULL << 7)
 
 #if defined(__linux__)
 
@@ -169,6 +193,18 @@ static long syscall_impl_5_args(long number, long arg1, long arg2, long arg3,
 #define RISCV_HWPROBE_EXT_ZACAS (1ULL << 34)
 #define RISCV_HWPROBE_EXT_ZICOND (1ULL << 35)
 #define RISCV_HWPROBE_EXT_ZIHINTPAUSE (1ULL << 36)
+#define RISCV_HWPROBE_EXT_ZVE32X (1ULL << 37)
+#define RISCV_HWPROBE_EXT_ZVE32F (1ULL << 38)
+#define RISCV_HWPROBE_EXT_ZVE64X (1ULL << 39)
+#define RISCV_HWPROBE_EXT_ZVE64F (1ULL << 40)
+#define RISCV_HWPROBE_EXT_ZVE64D (1ULL << 41)
+#define RISCV_HWPROBE_EXT_ZIMOP (1ULL << 42)
+#define RISCV_HWPROBE_EXT_ZCA (1ULL << 43)
+#define RISCV_HWPROBE_EXT_ZCB (1ULL << 44)
+#define RISCV_HWPROBE_EXT_ZCD (1ULL << 45)
+#define RISCV_HWPROBE_EXT_ZCF (1ULL << 46)
+#define RISCV_HWPROBE_EXT_ZCMOP (1ULL << 47)
+#define RISCV_HWPROBE_EXT_ZAWRS (1ULL << 48)
 #define RISCV_HWPROBE_KEY_CPUPERF_0 5
 #define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
 #define RISCV_HWPROBE_MISALIGNED_EMULATED (1ULL << 0)
@@ -271,6 +307,18 @@ static void initRISCVFeature(struct riscv_hwprobe Hwprobes[]) {
   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZTSO);
   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZACAS);
   SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZICOND);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32X);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE32F);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64X);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64F);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZVE64D);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZIMOP);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCA);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCB);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCD);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCF);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZCMOP);
+  SET_RISCV_HWPROBE_EXT_SINGLE_RISCV_FEATURE(ZAWRS);
 
   for (i = 0; i < RISCV_FEATURE_BITS_LENGTH; i++)
     __riscv_feature_bits.features[i] = features[i];
diff --git a/llvm/include/llvm/TargetParser/RISCVISAInfo.h b/llvm/include/llvm/TargetParser/RISCVISAInfo.h
index d71ff174bf0d2..2f81307dcfabf 100644
--- a/llvm/include/llvm/TargetParser/RISCVISAInfo.h
+++ b/llvm/include/llvm/TargetParser/RISCVISAInfo.h
@@ -80,10 +80,14 @@ class RISCVISAInfo {
                                      std::set<StringRef> &EnabledFeatureNames,
                                      StringMap<StringRef> &DescMap);
 
-  /// Return the bit position (in group 0) of __riscv_feature_bits.  Returns
+  /// Return the bit position of __riscv_feature_bits.  Returns
   /// -1 if not supported.
   static int getRISCVFeaturesBitPosition(StringRef Ext);
 
+  /// Return the group id of __riscv_feature_bits.  Returns
+  /// -1 if not supported.
+  static int getRISCVFeaturesGroupID(StringRef Ext);
+
 private:
   RISCVISAInfo(unsigned XLen) : XLen(XLen) {}
 
diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp
index 9f650b87f2b39..033bf096625aa 100644
--- a/llvm/lib/TargetParser/RISCVISAInfo.cpp
+++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp
@@ -1023,40 +1023,57 @@ std::string RISCVISAInfo::getTargetFeatureForExtension(StringRef Ext) {
 
 struct RISCVExtBit {
   const StringLiteral ext;
+  uint8_t groupid;
   uint8_t bitpos;
 };
 
-/// Maps extensions with assigned bit positions within group 0 of
-/// __riscv_features_bits to their respective bit position.  At the
-/// moment all extensions are within group 0.
-constexpr static RISCVExtBit RISCVGroup0BitPositions[] = {
-    {"a", 0},          {"c", 2},
-    {"d", 3},          {"f", 5},
-    {"i", 8},          {"m", 12},
-    {"v", 21},         {"zacas", 26},
-    {"zba", 27},       {"zbb", 28},
-    {"zbc", 29},       {"zbkb", 30},
-    {"zbkc", 31},      {"zbkx", 32},
-    {"zbs", 33},       {"zfa", 34},
-    {"zfh", 35},       {"zfhmin", 36},
-    {"zicboz", 37},    {"zicond", 38},
-    {"zihintntl", 39}, {"zihintpause", 40},
-    {"zknd", 41},      {"zkne", 42},
-    {"zknh", 43},      {"zksed", 44},
-    {"zksh", 45},      {"zkt", 46},
-    {"ztso", 47},      {"zvbb", 48},
-    {"zvbc", 49},      {"zvfh", 50},
-    {"zvfhmin", 51},   {"zvkb", 52},
-    {"zvkg", 53},      {"zvkned", 54},
-    {"zvknha", 55},    {"zvknhb", 56},
-    {"zvksed", 57},    {"zvksh", 58},
-    {"zvkt", 59}};
+constexpr static RISCVExtBit RISCVBitPositions[] = {
+    {"a", 0, 0},          {"c", 0, 2},
+    {"d", 0, 3},          {"f", 0, 5},
+    {"i", 0, 8},          {"m", 0, 12},
+    {"v", 0, 21},         {"zacas", 0, 26},
+    {"zba", 0, 27},       {"zbb", 0, 28},
+    {"zbc", 0, 29},       {"zbkb", 0, 30},
+    {"zbkc", 0, 31},      {"zbkx", 0, 32},
+    {"zbs", 0, 33},       {"zfa", 0, 34},
+    {"zfh", 0, 35},       {"zfhmin", 0, 36},
+    {"zicboz", 0, 37},    {"zicond", 0, 38},
+    {"zihintntl", 0, 39}, {"zihintpause", 0, 40},
+    {"zknd", 0, 41},      {"zkne", 0, 42},
+    {"zknh", 0, 43},      {"zksed", 0, 44},
+    {"zksh", 0, 45},      {"zkt", 0, 46},
+    {"ztso", 0, 47},      {"zvbb", 0, 48},
+    {"zvbc", 0, 49},      {"zvfh", 0, 50},
+    {"zvfhmin", 0, 51},   {"zvkb", 0, 52},
+    {"zvkg", 0, 53},      {"zvkned", 0, 54},
+    {"zvknha", 0, 55},    {"zvknhb", 0, 56},
+    {"zvksed", 0, 57},    {"zvksh", 0, 58},
+    {"zvkt", 0, 59},      {"zve32x", 0, 60},
+    {"zve32f", 0, 61},    {"zve64x", 0, 62},
+    {"zve64x", 0, 63},    {"zve64d", 1, 0},
+    {"zimop", 1, 1},      {"zca", 1, 2},
+    {"zcb", 1, 3},        {"zcd", 1, 4},
+    {"zcf", 1, 5},        {"zcmop", 1, 6},
+    {"zawrs", 1, 7}};
+
 int RISCVISAInfo::getRISCVFeaturesBitPosition(StringRef Ext) {
   // Note that this code currently accepts mixed case extension names, but
   // does not handle extension versions at all.  That's probably fine because
   // there's only one extension version in the __riscv_feature_bits vector.
-  for (auto E : RISCVGroup0BitPositions)
+  for (auto E : RISCVBitPositions)
     if (E.ext.equals_insensitive(Ext))
       return E.bitpos;
   return -1;
 }
+
+// TODO: merge getRISCVFeaturesBitPosition and getRISCVFeaturesGroupID into
+// single function.
+int RISCVISAInfo::getRISCVFeaturesGroupID(StringRef Ext) {
+  // Note that this code currently accepts mixed case extension names, but
+  // does not handle extension versions at all.  That's probably fine because
+  // there's only one extension version in the __riscv_feature_bits vector.
+  for (auto E : RISCVBitPositions)
+    if (E.ext.equals_insensitive(Ext))
+      return E.groupid;
+  return -1;
+}

@llvmbot llvmbot added the clang:frontend Language frontend issues, e.g. anything involving "Sema" label Aug 7, 2024
@BeMg BeMg requested a review from topperc August 8, 2024 03:34
Copy link
Collaborator

@topperc topperc left a comment

Choose a reason for hiding this comment

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

LGTM

@BeMg BeMg merged commit 82f52d9 into llvm:main Aug 8, 2024
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V 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 compiler-rt:builtins compiler-rt
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants