diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -48,6 +48,8 @@ {"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 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -447,8 +447,16 @@ 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; @@ -887,6 +895,17 @@ 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()); @@ -894,7 +913,7 @@ 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; @@ -1198,9 +1217,8 @@ } 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 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp @@ -146,7 +146,7 @@ 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 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -41,6 +41,13 @@ 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 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -799,6 +799,9 @@ 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 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -76,6 +76,7 @@ bool HasStdExtZbs = false; bool HasStdExtZbt = false; bool HasStdExtV = false; + bool HasStdExtZihintpause = false; bool HasStdExtZvlsseg = false; bool HasStdExtZfhmin = false; bool HasStdExtZfh = false; @@ -150,6 +151,7 @@ bool hasStdExtZbs() const { return HasStdExtZbs; } bool hasStdExtZbt() const { return HasStdExtZbt; } bool hasStdExtV() const { return HasStdExtV; } + bool hasStdExtZihintpause() const { return HasStdExtZihintpause; } bool hasStdExtZvlsseg() const { return HasStdExtZvlsseg; } bool hasStdExtZvl() const { return ZvlLen != ExtZvl::NotSet; } bool hasStdExtZfhmin() const { return HasStdExtZfhmin; } diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll --- 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 @@ -24,6 +25,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 @@ -45,6 +47,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_zfhmin1p0" ; RV32ZBA: .attribute 5, "rv32i2p0_zba1p0" @@ -65,6 +68,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_zfhmin1p0" ; 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 --- 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 --- 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] @@ -173,6 +173,7 @@ amomaxu.w s5, s4, (s3) # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'A' (Atomic Instructions) fadd.s ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'F' (Single-Precision Floating-Point) fadd.h ft0, ft1, ft2 # CHECK: :[[@LINE]]:1: error: instruction requires the following: 'Zfh' (Half-Precision Floating-Point) +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 --- /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 --- /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