diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 41d836330b38c2..1f8a8cd1462c9d 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -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; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 51d1162c6e403c..d1af7fde157b64 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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); } diff --git a/clang/test/CodeGen/builtin-cpu-supports.c b/clang/test/CodeGen/builtin-cpu-supports.c index 92c407653e660f..071d627b7181b5 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 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]+]] { @@ -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(); @@ -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 diff --git a/compiler-rt/lib/builtins/cpu_model/riscv.c b/compiler-rt/lib/builtins/cpu_model/riscv.c index 92931fae64fbf3..0c443025b74c63 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 d71ff174bf0d27..dd00e12cdf6c1e 100644 --- a/llvm/include/llvm/TargetParser/RISCVISAInfo.h +++ b/llvm/include/llvm/TargetParser/RISCVISAInfo.h @@ -80,9 +80,9 @@ class RISCVISAInfo { std::set &EnabledFeatureNames, StringMap &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 getRISCVFeaturesBitsInfo(StringRef Ext); private: RISCVISAInfo(unsigned XLen) : XLen(XLen) {} diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 9f650b87f2b393..59df02daf63265 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -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 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); }