Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions core_descs/ExampleRV32K.core_desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// RUN: pattern-gen %s -O 3 --mattr=+m --riscv-xlen 32 | FileCheck --check-prefixes=CHECK-RV32,CHECK-RV32-EXTEND -allow-unused-prefixes %s
// RUN: pattern-gen %s -O 3 --no-extend --mattr=+m --riscv-xlen 32 | FileCheck --check-prefixes=CHECK-RV32,CHECK-RV32-NOEXTED -allow-unused-prefixes %s

InstructionSet XExampleRV32 extends RISCVBase {
instructions {
// CHECK-RV32: Pattern for K_LLI: (i32 uimm32:$imm)
K_LLI {
encoding: 4'b0000 :: imm[31:0] :: rd[4:0] :: 7'b1011111;
assembly: {"k.lli", "{name(rd)}, {imm}"};
behavior: {
if ((rd % RFS) != 0)
// imm -> unsigned!
// X[rd % RFS] = (unsigned<XLEN>) ((unsigned) imm);
X[rd] = (unsigned<XLEN>) ((unsigned) imm);
}
}
// CHECK-RV32: Pattern for K_ADDI: (add GPR:$rs1, (i32 uimm24:$imm))
K_ADDI {
encoding: 4'b0001 :: imm[23:0] :: rs1[4:0] :: 3'b000 :: rd[4:0] :: 7'b1011111;
assembly: {"k.addi", "{name(rd)}, {name(rs1)}, {imm}"};
behavior: {
if ((rd % RFS) != 0) {
// X[rd % RFS] = X[rs1 % RFS] + (signed)imm;
X[rd] = X[rs1] + (signed)imm;
}
}
}
// CHECK-RV32: Pattern for K_ANDI: (and GPR:$rs1, (i32 uimm24:$imm))
K_ANDI {
encoding: 4'b0001 :: imm[23:0] :: rs1[4:0] :: 3'b001 :: rd[4:0] :: 7'b1011111;
assembly: {"k.andi", "{name(rd)}, {name(rs1)}, {imm}"};
behavior: {
if ((rd % RFS) != 0) {
// X[rd % RFS] = X[rs1 % RFS] & (unsigned)imm;
X[rd] = X[rs1] & (unsigned)imm;
}
}
}
// CHECK-RV32: Pattern for K_XORI: (xor GPR:$rs1, (i32 uimm24:$imm))
K_XORI {
encoding: 4'b0001 :: imm[23:0] :: rs1[4:0] :: 3'b010 :: rd[4:0] :: 7'b1011111;
assembly: {"k.xori", "{name(rd)}, {name(rs1)}, {imm}"};
behavior: {
if ((rd % RFS) != 0) {
// X[rd % RFS] = X[rs1 % RFS] ^ (unsigned)imm;
X[rd] = X[rs1] ^ (unsigned)imm;
}
}
}
// CHECK-RV32: Pattern for K_ORI: (or GPR:$rs1, (i32 uimm24:$imm))
K_ORI {
encoding: 4'b0001 :: imm[23:0] :: rs1[4:0] :: 3'b011 :: rd[4:0] :: 7'b1011111;
assembly: {"k.ori", "{name(rd)}, {name(rs1)}, {imm}"};
behavior: {
if ((rd % RFS) != 0) {
// X[rd % RFS] = X[rs1 % RFS] | (unsigned)imm;
X[rd] = X[rs1] | (unsigned)imm;
}
}
}
}
}
86 changes: 86 additions & 0 deletions core_descs/ExampleRV32K.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
; ModuleID = 'mod'
source_filename = "mod"

define void @implK_LLI(i32 %imm, ptr noalias %rd) {
%1 = and i32 %imm, -1
%2 = icmp eq i32 %imm, %1
call void @llvm.assume(i1 %2)
br i1 true, label %3, label %4

3: ; preds = %0
store i32 %imm, ptr %rd, align 4
br label %4

4: ; preds = %3, %0
ret void
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write)
declare void @llvm.assume(i1 noundef) #0

define void @implK_ADDI(i32 %imm, ptr %rs1, ptr noalias %rd) {
%1 = and i32 %imm, 16777215
%2 = icmp eq i32 %imm, %1
call void @llvm.assume(i1 %2)
br i1 true, label %3, label %5

3: ; preds = %0
%rs1.v = load i32, ptr %rs1, align 4
%4 = add i32 %rs1.v, %imm
store i32 %4, ptr %rd, align 4
br label %5

5: ; preds = %3, %0
ret void
}

define void @implK_ANDI(i32 %imm, ptr %rs1, ptr noalias %rd) {
%1 = and i32 %imm, 16777215
%2 = icmp eq i32 %imm, %1
call void @llvm.assume(i1 %2)
br i1 true, label %3, label %5

3: ; preds = %0
%rs1.v = load i32, ptr %rs1, align 4
%4 = and i32 %rs1.v, %imm
store i32 %4, ptr %rd, align 4
br label %5

5: ; preds = %3, %0
ret void
}

define void @implK_XORI(i32 %imm, ptr %rs1, ptr noalias %rd) {
%1 = and i32 %imm, 16777215
%2 = icmp eq i32 %imm, %1
call void @llvm.assume(i1 %2)
br i1 true, label %3, label %5

3: ; preds = %0
%rs1.v = load i32, ptr %rs1, align 4
%4 = xor i32 %rs1.v, %imm
store i32 %4, ptr %rd, align 4
br label %5

5: ; preds = %3, %0
ret void
}

define void @implK_ORI(i32 %imm, ptr %rs1, ptr noalias %rd) {
%1 = and i32 %imm, 16777215
%2 = icmp eq i32 %imm, %1
call void @llvm.assume(i1 %2)
br i1 true, label %3, label %5

3: ; preds = %0
%rs1.v = load i32, ptr %rs1, align 4
%4 = or i32 %rs1.v, %imm
store i32 %4, ptr %rd, align 4
br label %5

5: ; preds = %3, %0
ret void
}

attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }

33 changes: 33 additions & 0 deletions core_descs/ExampleRV32K.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
let Predicates = [HasVendorXCValu] in {

let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1, Constraints = "" in def K_LLI_ : RVInst_K_LLI<(outs GPR:$rd), (ins uimm32:$imm)>;

def : Pat<
(i32 (i32 uimm32:$imm)),
(K_LLI_ uimm32:$imm)>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1, Constraints = "" in def K_ADDI_ : RVInst_K_ADDI<(outs GPR:$rd), (ins uimm24:$imm, GPR:$rs1)>;

def : Pat<
(i32 (add GPR:$rs1, (i32 uimm24:$imm))),
(K_ADDI_ uimm24:$imm, GPR:$rs1)>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1, Constraints = "" in def K_ANDI_ : RVInst_K_ANDI<(outs GPR:$rd), (ins uimm24:$imm, GPR:$rs1)>;

def : Pat<
(i32 (and GPR:$rs1, (i32 uimm24:$imm))),
(K_ANDI_ uimm24:$imm, GPR:$rs1)>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1, Constraints = "" in def K_XORI_ : RVInst_K_XORI<(outs GPR:$rd), (ins uimm24:$imm, GPR:$rs1)>;

def : Pat<
(i32 (xor GPR:$rs1, (i32 uimm24:$imm))),
(K_XORI_ uimm24:$imm, GPR:$rs1)>;

let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 1, Constraints = "" in def K_ORI_ : RVInst_K_ORI<(outs GPR:$rd), (ins uimm24:$imm, GPR:$rs1)>;

def : Pat<
(i32 (or GPR:$rs1, (i32 uimm24:$imm))),
(K_ORI_ uimm24:$imm, GPR:$rs1)>;

}
5 changes: 4 additions & 1 deletion llvm/tools/pattern-gen/lib/InstrInfo.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
#include "InstrInfo.hpp"
#include <sstream>

Check warning on line 2 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

#includes are not sorted properly
#include <algorithm>

std::string EncodingToTablgen(CDSLInstr const& instr)

Check warning on line 5 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for parameter 'instr'
{
std::stringstream s;

Check warning on line 7 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for variable 's'

uint8_t size = instr.size;

Check warning on line 9 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for variable 'size'
std::string base = (size == 48 ? "RVInst48" : (size == 16 ? "RVInst16" : "RVInst"));

Check warning on line 10 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for variable 'base'

s << "class RVInst_" << instr.name << "<dag outs, dag ins>"
<< " : RVInst<outs, ins, \"" << instr.mnemonic << "\", \"" << instr.argString << "\", [], InstFormatOther> {\n";
<< " : " << base << "<outs, ins, \"" << instr.mnemonic << "\", \"" << instr.argString << "\", [], InstFormatOther> {\n";

for (auto const& f : instr.fields)
if (f.type & (CDSLInstr::FieldType::NON_CONST))
Expand All @@ -32,7 +35,7 @@
return s.str();
}

void PrintInstrsAsTableGen (std::vector<CDSLInstr> const& instrs, std::ostream& ostream)

Check warning on line 38 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for parameter 'ostream'

Check warning on line 38 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for parameter 'instrs'

Check warning on line 38 in llvm/tools/pattern-gen/lib/InstrInfo.cpp

View workflow job for this annotation

GitHub Actions / Run linters

invalid case style for function 'PrintInstrsAsTableGen'
{
for (auto const& instr : instrs)
ostream << EncodingToTablgen(instr) << '\n';
Expand Down
5 changes: 3 additions & 2 deletions llvm/tools/pattern-gen/lib/InstrInfo.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#pragma once

Check warning on line 1 in llvm/tools/pattern-gen/lib/InstrInfo.hpp

View workflow job for this annotation

GitHub Actions / Run linters

header is missing header guard
#include "llvm/ADT/SmallVector.h"
#include <cstdint>

Check warning on line 3 in llvm/tools/pattern-gen/lib/InstrInfo.hpp

View workflow job for this annotation

GitHub Actions / Run linters

#includes are not sorted properly
Expand All @@ -15,7 +15,7 @@
uint8_t len;
uint8_t dstOffset;
uint8_t srcOffset;
uint32_t val;
uint64_t val;
};

enum FieldType
Expand All @@ -34,12 +34,13 @@
struct Field
{
uint8_t len;
uint32_t constV;
uint64_t constV;
std::string_view ident;
uint32_t identIdx;
FieldType type;
};

uint8_t size;
std::string name;
std::string mnemonic;
std::string argString;
Expand Down
23 changes: 18 additions & 5 deletions llvm/tools/pattern-gen/lib/Parser.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#include "Parser.hpp"
#include "InstrInfo.hpp"
#include "Token.hpp"
Expand Down Expand Up @@ -1260,7 +1260,7 @@
pop_cur(ts, EncodingKeyword);
pop_cur(ts, Colon);

uint offset = 32;
uint offset = 48;
uint preDefIdx = instr.fields.size();

while (1) {
Expand Down Expand Up @@ -1329,18 +1329,31 @@
syntax_error(ts);
}
if (pop_cur_if(ts, Semicolon)) {
if (offset != 0)
error("instruction length is not 32 bits", ts);
if (offset != 0) {
if (offset != 16 && offset != 32) {
error("instruction length is not 16/32/48 bits", ts);
}
// Shift the field offsets by 16/32 bits
for (auto &frag : instr.frags)
if (frag.idx == 255) {
frag.srcOffset = frag.srcOffset - offset;
frag.dstOffset = frag.dstOffset - offset;
} else {
frag.dstOffset = frag.dstOffset - offset;
}
}
break;
}
pop_cur(ts, BitwiseConcat);
}
uint8_t size = 48 - offset;
instr.size = size;

// Rather than splitting up the constant bits of the instruction into multiple
// fields, we use one trailing constant field of size 32. FieldFragments can
// fields, we use one trailing constant field of size 32/48. FieldFragments can
// index into relevant sections of this single field.
instr.fields.push_back(CDSLInstr::Field{
.len = 32, .constV = 0, .type = CDSLInstr::FieldType::CONST});
.len = size, .constV = 0, .type = CDSLInstr::FieldType::CONST});
if (instr.fields.size() > 255)
error("too many instruction fields", ts);
uint8_t constIdx = instr.fields.size() - 1;
Expand Down