From 005fd8aa702edbc532763038365575da96e5787d Mon Sep 17 00:00:00 2001 From: Shao-Ce SUN Date: Thu, 20 Jan 2022 23:49:55 +0800 Subject: [PATCH] [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, ' and 'fence , 0'. This patch revised from @mundaym's D93019. Reviewed By: asb Differential Revision: https://reviews.llvm.org/D117789 --- llvm/lib/Support/RISCVISAInfo.cpp | 2 ++ llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp | 30 +++++++++++++++++----- .../Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp | 2 +- llvm/lib/Target/RISCV/RISCV.td | 7 +++++ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 3 +++ llvm/lib/Target/RISCV/RISCVSubtarget.h | 2 ++ llvm/test/CodeGen/RISCV/attributes.ll | 4 +++ .../MC/Disassembler/RISCV/unknown-fence-field.txt | 9 ------- llvm/test/MC/RISCV/rv32i-invalid.s | 11 ++++---- llvm/test/MC/RISCV/rv32zihintpause-valid.s | 20 +++++++++++++++ llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s | 24 +++++++++++++++++ 11 files changed, 93 insertions(+), 21 deletions(-) delete mode 100644 llvm/test/MC/Disassembler/RISCV/unknown-fence-field.txt create mode 100644 llvm/test/MC/RISCV/rv32zihintpause-valid.s create mode 100644 llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 2b3395b..a6d4e0b 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -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}}, diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 01f36e6..100e23d 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -447,8 +447,16 @@ public: bool isFenceArg() const { if (!isImm()) return false; - const MCExpr *Val = getImm(); - auto *SVal = dyn_cast(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(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(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(); diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp index 3268740..cfac3f7 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -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, diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index e32a8fb..f036696 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -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)", diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index ee6a74b..952910c 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -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)>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 34c6e8e..7d570a4 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -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; } diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index ce5b143..b5acd9b2 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -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" diff --git a/llvm/test/MC/Disassembler/RISCV/unknown-fence-field.txt b/llvm/test/MC/Disassembler/RISCV/unknown-fence-field.txt deleted file mode 100644 index 5b20994..0000000 --- a/llvm/test/MC/Disassembler/RISCV/unknown-fence-field.txt +++ /dev/null @@ -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 diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s index 500a0a3..5747512 100644 --- a/llvm/test/MC/RISCV/rv32i-invalid.s +++ b/llvm/test/MC/RISCV/rv32i-invalid.s @@ -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 diff --git a/llvm/test/MC/RISCV/rv32zihintpause-valid.s b/llvm/test/MC/RISCV/rv32zihintpause-valid.s new file mode 100644 index 0000000..3ffc387 --- /dev/null +++ b/llvm/test/MC/RISCV/rv32zihintpause-valid.s @@ -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 diff --git a/llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s b/llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s new file mode 100644 index 0000000..d505029 --- /dev/null +++ b/llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s @@ -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 -- 2.7.4