[RISCV] Add support for Zihintpause extention

Add support for the 'pause' hint instruction as an alias for
'fence w, 0'. To do this allow the 'fence' operands pred and succ
to be set to 0 (the empty set). This will also allow future hints
to be encoded as 'fence 0, <x>' and 'fence <x>, 0'.

This patch revised from @mundaym's D93019.

Reviewed By: asb

Differential Revision: https://reviews.llvm.org/D117789
This commit is contained in:
Shao-Ce SUN 2022-01-20 23:49:55 +08:00
parent 6f53960d64
commit 005fd8aa70
11 changed files with 93 additions and 21 deletions

View File

@ -48,6 +48,8 @@ static const RISCVSupportedExtension SupportedExtensions[] = {
{"d", RISCVExtensionVersion{2, 0}},
{"c", RISCVExtensionVersion{2, 0}},
{"zihintpause", RISCVExtensionVersion{2, 0}},
{"zfhmin", RISCVExtensionVersion{1, 0}},
{"zfh", RISCVExtensionVersion{1, 0}},

View File

@ -447,8 +447,16 @@ public:
bool isFenceArg() const {
if (!isImm())
return false;
const MCExpr *Val = getImm();
auto *SVal = dyn_cast<MCSymbolRefExpr>(Val);
int64_t Imm;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
if (evaluateConstantImm(getImm(), Imm, VK)) {
// Only accept 0 as a constant immediate.
return VK == RISCVMCExpr::VK_RISCV_None && Imm == 0;
}
auto *SVal = dyn_cast<MCSymbolRefExpr>(getImm());
if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None)
return false;
@ -897,6 +905,17 @@ public:
void addFenceArgOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
int64_t Constant = 0;
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
if (evaluateConstantImm(getImm(), Constant, VK)) {
if (Constant == 0) {
Inst.addOperand(MCOperand::createImm(Constant));
return;
}
llvm_unreachable("FenceArg must contain only [iorw] or be 0");
}
// isFenceArg has validated the operand, meaning this cast is safe
auto SE = cast<MCSymbolRefExpr>(getImm());
@ -904,7 +923,7 @@ public:
for (char c : SE->getSymbol().getName()) {
switch (c) {
default:
llvm_unreachable("FenceArg must contain only [iorw]");
llvm_unreachable("FenceArg must contain only [iorw] or be 0");
case 'i':
Imm |= RISCVFenceField::I;
break;
@ -1208,9 +1227,8 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
}
case Match_InvalidFenceArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();
return Error(
ErrorLoc,
"operand must be formed of letters selected in-order from 'iorw'");
return Error(ErrorLoc, "operand must be formed of letters selected "
"in-order from 'iorw' or be 0");
}
case Match_InvalidFRMArg: {
SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc();

View File

@ -146,7 +146,7 @@ void RISCVInstPrinter::printFenceArg(const MCInst *MI, unsigned OpNo,
if ((FenceArg & RISCVFenceField::W) != 0)
O << 'w';
if (FenceArg == 0)
O << "unknown";
O << "0";
}
void RISCVInstPrinter::printFRMArg(const MCInst *MI, unsigned OpNo,

View File

@ -41,6 +41,13 @@ def HasStdExtD : Predicate<"Subtarget->hasStdExtD()">,
AssemblerPredicate<(all_of FeatureStdExtD),
"'D' (Double-Precision Floating-Point)">;
def FeatureStdExtZihintpause
: SubtargetFeature<"zihintpause", "HasStdExtZihintpause", "true",
"'zihintpause' (Pause Hint)">;
def HasStdExtZihintpause : Predicate<"Subtarget->hasStdExtZihintpause()">,
AssemblerPredicate<(all_of FeatureStdExtZihintpause),
"'Zihintpause' (Pause Hint)">;
def FeatureStdExtZfhmin
: SubtargetFeature<"zfhmin", "HasStdExtZfhmin", "true",
"'Zfhmin' (Half-Precision Floating-Point Minimal)",

View File

@ -799,6 +799,9 @@ def : InstAlias<"jalr $rd, $rs, $offset", (JALR GPR:$rd, GPR:$rs, simm12:$offset
def : InstAlias<"fence", (FENCE 0xF, 0xF)>; // 0xF == iorw
let Predicates = [HasStdExtZihintpause] in
def : InstAlias<"pause", (FENCE 0x1, 0x0)>; // 0x1 == w
def : InstAlias<"rdinstret $rd", (CSRRS GPR:$rd, INSTRET.Encoding, X0)>;
def : InstAlias<"rdcycle $rd", (CSRRS GPR:$rd, CYCLE.Encoding, X0)>;
def : InstAlias<"rdtime $rd", (CSRRS GPR:$rd, TIME.Encoding, X0)>;

View File

@ -65,6 +65,7 @@ private:
bool HasStdExtF = false;
bool HasStdExtD = false;
bool HasStdExtC = false;
bool HasStdExtZihintpause = false;
bool HasStdExtZba = false;
bool HasStdExtZbb = false;
bool HasStdExtZbc = false;
@ -157,6 +158,7 @@ public:
bool hasStdExtD() const { return HasStdExtD; }
bool hasStdExtC() const { return HasStdExtC; }
bool hasStdExtV() const { return HasStdExtV; }
bool hasStdExtZihintpause() const { return HasStdExtZihintpause; }
bool hasStdExtZba() const { return HasStdExtZba; }
bool hasStdExtZbb() const { return HasStdExtZbb; }
bool hasStdExtZbc() const { return HasStdExtZbc; }

View File

@ -5,6 +5,7 @@
; RUN: llc -mtriple=riscv32 -mattr=+f %s -o - | FileCheck --check-prefix=RV32F %s
; RUN: llc -mtriple=riscv32 -mattr=+d %s -o - | FileCheck --check-prefix=RV32D %s
; RUN: llc -mtriple=riscv32 -mattr=+c %s -o - | FileCheck --check-prefix=RV32C %s
; RUN: llc -mtriple=riscv32 -mattr=+zihintpause %s -o - | FileCheck --check-prefix=RV32ZIHINTPAUSE %s
; RUN: llc -mtriple=riscv32 -mattr=+zfhmin %s -o - | FileCheck --check-prefix=RV32ZFHMIN %s
; RUN: llc -mtriple=riscv32 -mattr=+zfh %s -o - | FileCheck --check-prefix=RV32ZFH %s
; RUN: llc -mtriple=riscv32 -mattr=+zba %s -o - | FileCheck --check-prefix=RV32ZBA %s
@ -37,6 +38,7 @@
; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefix=RV64F %s
; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefix=RV64D %s
; RUN: llc -mtriple=riscv64 -mattr=+c %s -o - | FileCheck --check-prefix=RV64C %s
; RUN: llc -mtriple=riscv64 -mattr=+zihintpause %s -o - | FileCheck --check-prefix=RV64ZIHINTPAUSE %s
; RUN: llc -mtriple=riscv64 -mattr=+zfhmin %s -o - | FileCheck --check-prefix=RV64ZFHMIN %s
; RUN: llc -mtriple=riscv64 -mattr=+zfh %s -o - | FileCheck --check-prefix=RV64ZFH %s
; RUN: llc -mtriple=riscv64 -mattr=+zba %s -o - | FileCheck --check-prefix=RV64ZBA %s
@ -70,6 +72,7 @@
; RV32F: .attribute 5, "rv32i2p0_f2p0"
; RV32D: .attribute 5, "rv32i2p0_f2p0_d2p0"
; RV32C: .attribute 5, "rv32i2p0_c2p0"
; RV32ZIHINTPAUSE: .attribute 5, "rv32i2p0_zihintpause2p0"
; RV32ZFHMIN: .attribute 5, "rv32i2p0_f2p0_zfhmin1p0"
; RV32ZFH: .attribute 5, "rv32i2p0_f2p0_zfh1p0"
; RV32ZBA: .attribute 5, "rv32i2p0_zba1p0"
@ -103,6 +106,7 @@
; RV64F: .attribute 5, "rv64i2p0_f2p0"
; RV64D: .attribute 5, "rv64i2p0_f2p0_d2p0"
; RV64C: .attribute 5, "rv64i2p0_c2p0"
; RV64ZIHINTPAUSE: .attribute 5, "rv64i2p0_zihintpause2p0"
; RV64ZFHMIN: .attribute 5, "rv64i2p0_f2p0_zfhmin1p0"
; RV64ZFH: .attribute 5, "rv64i2p0_f2p0_zfh1p0"
; RV64ZBA: .attribute 5, "rv64i2p0_zba1p0"

View File

@ -1,9 +0,0 @@
# RUN: llvm-mc -disassemble -triple=riscv32 < %s 2>&1 | FileCheck %s
# RUN: llvm-mc -disassemble -triple=riscv64 < %s 2>&1 | FileCheck %s
#
# Test generated by a LLVM MC Disassembler Protocol Buffer Fuzzer
# for the RISC-V assembly language.
# This decodes as fence , iorw with invalid fence field as 0.
[0x0f 0x00 0xf0 0x00]
# CHECK: fence unknown, iorw

View File

@ -2,11 +2,11 @@
# Out of range immediates
## fencearg
fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw'
fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw'
fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw'
fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw' or be 0
fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw' or be 0
fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' or be 0
## uimm5
slli a0, a0, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]
@ -177,6 +177,7 @@ sh1add a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the followi
clz a0, a1 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbb' (Basic Bit-Manipulation)
clmul a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbc' (Carry-Less Multiplication)
bset a0, a1, a2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zbs' (Single-Bit Instructions)
pause # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zihintpause' (Pause Hint)
# Using floating point registers when integer registers are expected
addi a2, ft0, 24 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction

View File

@ -0,0 +1,20 @@
# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause -riscv-no-aliases -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause -riscv-no-aliases -show-encoding \
# RUN: | FileCheck -check-prefixes=CHECK-ASM,CHECK-ASM-AND-OBJ %s
# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -M no-aliases -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -M no-aliases -d -r - \
# RUN: | FileCheck --check-prefix=CHECK-ASM-AND-OBJ %s
# CHECK-ASM-AND-OBJ: fence w, 0
# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x01]
fence w,0
# CHECK-ASM-AND-OBJ: fence 0, w
# CHECK-ASM: encoding: [0x0f,0x00,0x10,0x00]
fence 0,w
# CHECK-ASM-AND-OBJ: fence 0, 0
# CHECK-ASM: encoding: [0x0f,0x00,0x00,0x00]
fence 0,0

View File

@ -0,0 +1,24 @@
# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause -M no-aliases \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
# RUN: llvm-mc %s -triple=riscv32 -mattr=+zihintpause \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause -M no-aliases \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
# RUN: llvm-mc %s -triple=riscv64 -mattr=+zihintpause \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -d -r -M no-aliases - \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
# RUN: llvm-mc -filetype=obj -triple riscv32 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -d -r - \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -d -r -M no-aliases - \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ-NOALIAS %s
# RUN: llvm-mc -filetype=obj -triple riscv64 -mattr=+zihintpause < %s \
# RUN: | llvm-objdump --mattr=+zihintpause -d -r - \
# RUN: | FileCheck -check-prefixes=CHECK-S-OBJ %s
# CHECK-S-OBJ-NOALIAS: fence w, 0
# CHECK-S-OBJ: pause
pause