https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/101632
>From 91ebb0568f28015006e3443221ae51f92c159dfb Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Fri, 2 Aug 2024 01:07:04 -0700 Subject: [PATCH 1/2] [RISCV] Suuport new bitmask for cpu_model --- clang/lib/CodeGen/CGBuiltin.cpp | 3 +- clang/test/CodeGen/builtin-cpu-supports.c | 50 ++++++++++---- compiler-rt/lib/builtins/cpu_model/riscv.c | 50 +++++++++++++- llvm/include/llvm/TargetParser/RISCVISAInfo.h | 6 +- llvm/lib/TargetParser/RISCVISAInfo.cpp | 69 ++++++++++++------- 5 files changed, 135 insertions(+), 43 deletions(-) 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; +} >From 53cca7fcf4573383925602813d360afcc4318a9f Mon Sep 17 00:00:00 2001 From: Piyou Chen <piyou.c...@sifive.com> Date: Wed, 7 Aug 2024 06:10:45 -0700 Subject: [PATCH 2/2] getRISCVFeaturesBitsInfo replace getRISCVFeaturesGroupID and getRISCVFeaturesBitPosition --- clang/lib/Basic/Targets/RISCV.cpp | 2 +- clang/lib/CodeGen/CGBuiltin.cpp | 6 ++++-- llvm/include/llvm/TargetParser/RISCVISAInfo.h | 10 +++------- llvm/lib/TargetParser/RISCVISAInfo.cpp | 18 +++--------------- 4 files changed, 11 insertions(+), 25 deletions(-) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 41d836330b38c..1f8a8cd1462c9 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 c903064b12cba..0af316c07311e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -14390,8 +14390,10 @@ Value *CodeGenFunction::EmitRISCVCpuSupports(const CallExpr *E) { return FeaturesBit; }; - int BitPos = RISCVISAInfo::getRISCVFeaturesBitPosition(FeatureStr); - int GroupID = RISCVISAInfo::getRISCVFeaturesGroupID(FeatureStr); + std::pair<int, int> BitsInfo = + RISCVISAInfo::getRISCVFeaturesBitsInfo(FeatureStr); + int GroupID = BitsInfo.first; + int BitPos = BitsInfo.second; assert(BitPos != -1 && "validation should have rejected this feature"); Value *MaskV = Builder.getInt64(1ULL << BitPos); Value *Bitset = Builder.CreateAnd(LoadFeatureBit(GroupID), MaskV); diff --git a/llvm/include/llvm/TargetParser/RISCVISAInfo.h b/llvm/include/llvm/TargetParser/RISCVISAInfo.h index 2f81307dcfabf..dd00e12cdf6c1 100644 --- a/llvm/include/llvm/TargetParser/RISCVISAInfo.h +++ b/llvm/include/llvm/TargetParser/RISCVISAInfo.h @@ -80,13 +80,9 @@ class RISCVISAInfo { std::set<StringRef> &EnabledFeatureNames, StringMap<StringRef> &DescMap); - /// 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); + /// 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) {} diff --git a/llvm/lib/TargetParser/RISCVISAInfo.cpp b/llvm/lib/TargetParser/RISCVISAInfo.cpp index 033bf096625aa..1ae886dba9603 100644 --- a/llvm/lib/TargetParser/RISCVISAInfo.cpp +++ b/llvm/lib/TargetParser/RISCVISAInfo.cpp @@ -1056,24 +1056,12 @@ constexpr static RISCVExtBit RISCVBitPositions[] = { {"zcf", 1, 5}, {"zcmop", 1, 6}, {"zawrs", 1, 7}}; -int RISCVISAInfo::getRISCVFeaturesBitPosition(StringRef Ext) { +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 : 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; + return std::make_pair<int, int>(E.groupid, E.bitpos); + return std::make_pair<int, int>(-1, -1); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits