Skip to content

Commit

Permalink
[RISCV] Support new groupid/bitmask for cpu_model (llvm#101632)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
BeMg committed Aug 8, 2024
1 parent 6673cf1 commit 82f52d9
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 50 deletions.
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,5 +483,5 @@ RISCVTargetInfo::checkCallingConvention(CallingConv CC) const {
bool RISCVTargetInfo::validateCpuSupports(StringRef Feature) const {
// Only allow extensions we have a known bit position for in the
// __riscv_feature_bits structure.
return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitPosition(Feature);
return -1 != llvm::RISCVISAInfo::getRISCVFeaturesBitsInfo(Feature).second;
}
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14462,10 +14462,10 @@ Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) {
return FeaturesBit;
};

int BitPos = RISCVISAInfo::getRISCVFeaturesBitPosition(FeatureStr);
auto [GroupID, BitPos] = RISCVISAInfo::getRISCVFeaturesBitsInfo(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);
}

Expand Down
50 changes: 36 additions & 14 deletions clang/test/CodeGen/builtin-cpu-supports.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 13, 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]+]] {
Expand Down Expand Up @@ -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 13, 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();
Expand All @@ -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 13;
return 0;
}
#endif
50 changes: 49 additions & 1 deletion compiler-rt/lib/builtins/cpu_model/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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__)

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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];
Expand Down
6 changes: 3 additions & 3 deletions llvm/include/llvm/TargetParser/RISCVISAInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ class RISCVISAInfo {
std::set<StringRef> &EnabledFeatureNames,
StringMap<StringRef> &DescMap);

/// Return the bit position (in group 0) of __riscv_feature_bits. Returns
/// -1 if not supported.
static int getRISCVFeaturesBitPosition(StringRef Ext);
/// Return the group id and bit position of __riscv_feature_bits. Returns
/// <-1, -1> if not supported.
static std::pair<int, int> getRISCVFeaturesBitsInfo(StringRef Ext);

private:
RISCVISAInfo(unsigned XLen) : XLen(XLen) {}
Expand Down
63 changes: 34 additions & 29 deletions llvm/lib/TargetParser/RISCVISAInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,40 +1023,45 @@ 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}};
int RISCVISAInfo::getRISCVFeaturesBitPosition(StringRef Ext) {
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}};

std::pair<int, int> RISCVISAInfo::getRISCVFeaturesBitsInfo(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;
return std::make_pair(E.groupid, E.bitpos);
return std::make_pair(-1, -1);
}

0 comments on commit 82f52d9

Please sign in to comment.