Skip to content

Commit

Permalink
[RISCV]Add support for resolving encoding conflicts among vendor spec…
Browse files Browse the repository at this point in the history
…ific CSRs

This patch adds the framework for resolving encoding conflicts among CSRs.

Specifically, this patch adds a support for emitting a new lookup function for
the primary key which return a pair of iterators pointing to first and last
value hence giving a range of values which satisfies the query.

While printing the CSR name during objdump, iterate over the range and print the
name of only that CSR which satisifes the feature requirement of subtarget.

Below is the signature of the new function that will be emitted for primary key:

```
std::pair<const SysReg *, const SysReg *>lookupSysRegByEncoding(uint16_t Encoding) {
  SysReg Key;
  Key.Encoding = Encoding;
  auto Table = ArrayRef(SysRegsList);
  auto It = std::equal_range(Table.begin(), Table.end(), Key,
    [](const SysReg &LHS, const SysReg &RHS) {
      if (LHS.Encoding < RHS.Encoding)
        return true;
      if (LHS.Encoding > RHS.Encoding)
        return false;
      return false;
    });

  auto Idx = It.first;
  if (Idx == Table.end() ||
      Key.Encoding != Idx->Encoding)
    return {nullptr, nullptr};

  return It;

```
  • Loading branch information
quic-garvgupt committed Jun 27, 2024
1 parent e258bb3 commit bc106a0
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 53 deletions.
8 changes: 8 additions & 0 deletions llvm/include/llvm/TableGen/SearchableTable.td
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ class GenericTable {

// See SearchIndex.EarlyOut
bit PrimaryKeyEarlyOut = false;

// See SearchIndex.ReturnRange
bit PrimaryKeyReturnRange = false;
}

// Define a record derived from this class to generate an additional search
Expand All @@ -135,6 +138,11 @@ class SearchIndex {
//
// Can only be used when the first field is an integral (non-string) type.
bit EarlyOut = false;

// If true, will generate a different function signature which will return
// a std::pair<> of iterators pointing to start and end value of the range
// e.g. lookupSysRegByEncoding returns multiple CSRs for same encoding.
bit ReturnRange = false;
}

// Legacy table type with integrated enum.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCVSystemOperands.td
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ def SysRegsList : GenericTable {

let PrimaryKey = [ "Encoding" ];
let PrimaryKeyName = "lookupSysRegByEncoding";
let PrimaryKeyReturnRange = false;
}

def lookupSysRegByName : SearchIndex {
Expand Down
118 changes: 118 additions & 0 deletions llvm/test/TableGen/EncodingConflict.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// RUN: llvm-tblgen -gen-searchable-tables -I %p/../../include %s | FileCheck %s

include "llvm/TableGen/SearchableTable.td"

class SysReg<string name, bits<12> op> {
string Name = name;
bits<12> Encoding = op;
code FeaturesRequired = [{ {} }];
}

def List1 : GenericTable {
let FilterClass = "SysReg";
let Fields = [
"Name", "Encoding", "FeaturesRequired",
];

let PrimaryKey = [ "Encoding" ];
let PrimaryKeyName = "lookupSysRegByEncoding";
let PrimaryKeyReturnRange = true;
}


let FeaturesRequired = [{ {Feature1} }] in {
def : SysReg<"csr1", 0x7C9>;
}

let FeaturesRequired = [{ {Feature2} }] in {
def : SysReg<"csr2", 0x7C9>;
}

// CHECK: #ifdef GET_List1_DECL
// CHECK-NEXT: std::pair<const SysReg *, const SysReg *>lookupSysRegByEncoding(uint16_t Encoding);
// CHECK-NEXT: #endif

// CHECK: #ifdef GET_List1_IMPL
// CHECK-NEXT: constexpr SysReg List1[] = {
// CHECK-NEXT: { "csr1", 0x7C9, {Feature1} }, // 0
// CHECK-NEXT: { "csr2", 0x7C9, {Feature2} }, // 1
// CHECK-NEXT: };

// CHECK: std::pair<const SysReg *, const SysReg *>lookupSysRegByEncoding(uint16_t Encoding) {
// CHECK-NEXT: SysReg Key;
// CHECK-NEXT: Key.Encoding = Encoding;
// CHECK-NEXT: auto Table = ArrayRef(List1);
// CHECK-NEXT: auto It = std::equal_range(Table.begin(), Table.end(), Key,
// CHECK-NEXT: [](const SysReg &LHS, const SysReg &RHS) {
// CHECK-NEXT: if (LHS.Encoding < RHS.Encoding)
// CHECK-NEXT: return true;
// CHECK-NEXT: if (LHS.Encoding > RHS.Encoding)
// CHECK-NEXT: return false;
// CHECK-NEXT: return false;
// CHECK-NEXT: });
// CHECK: auto Idx = It.first;
// CHECK-NEXT: if (Idx == Table.end() ||
// CHECK-NEXT: Key.Encoding != Idx->Encoding)
// CHECK-NEXT: return {nullptr, nullptr};

// CHECK: return It;
// CHECK-NEXT: }
// CHECK-NEXT: #endif

def List2 : GenericTable {
let FilterClass = "SysReg";
let Fields = [
"Name", "Encoding", "FeaturesRequired",
];
}

def lookupSysRegByName : SearchIndex {
let Table = List2;
let Key = [ "Name" ];
let ReturnRange = true;
}

// CHECK: #ifdef GET_List2_DECL
// CHECK-NEXT: std::pair<const SysReg *, const SysReg *>lookupSysRegByName(StringRef Name);
// CHECK-NEXT: #endif

// CHECK: #ifdef GET_List2_IMPL
// CHECK-NEXT: constexpr SysReg List2[] = {
// CHECK-NEXT: { "csr1", 0x7C9, {Feature1} }, // 0
// CHECK-NEXT: { "csr2", 0x7C9, {Feature2} }, // 1
// CHECK-NEXT: };

// CHECK: std::pair<const SysReg *, const SysReg *>lookupSysRegByName(StringRef Name) {
// CHECK-NEXT: struct IndexType {
// CHECK-NEXT: const char * Name;
// CHECK-NEXT: unsigned _index;
// CHECK-NEXT: };
// CHECK-NEXT: static const struct IndexType Index[] = {
// CHECK-NEXT: { "CSR1", 0 },
// CHECK-NEXT: { "CSR2", 1 },
// CHECK-NEXT: };

// CHECK: IndexType Key;
// CHECK-NEXT: Key.Name = Name.upper();
// CHECK-NEXT: auto Table = ArrayRef(Index);
// CHECK-NEXT: auto It = std::equal_range(Table.begin(), Table.end(), Key,
// CHECK-NEXT: [](const IndexType &LHS, const IndexType &RHS) {
// CHECK-NEXT: int CmpName = StringRef(LHS.Name).compare(RHS.Name);
// CHECK-NEXT: if (CmpName < 0) return true;
// CHECK-NEXT: if (CmpName > 0) return false;
// CHECK-NEXT: return false;
// CHECK-NEXT: });

// CHECK: auto Idx = It.first;
// CHECK-NEXT: if (Idx == Table.end() ||
// CHECK-NEXT: Key.Name != Idx->Name)
// CHECK-NEXT: return {nullptr, nullptr};

// CHECK: return It;
// CHECK-NEXT: }
// CHECK-NEXT: #endif

// CHECK: #undef GET_List1_DECL
// CHECK-NEXT: #undef GET_List1_IMPL
// CHECK-NEXT: #undef GET_List2_DECL
// CHECK-NEXT: #undef GET_List2_IMPL
Loading

0 comments on commit bc106a0

Please sign in to comment.