[RISCV] Add support for Zihintpause extention
authorShao-Ce SUN <shaoce@nj.iscas.ac.cn>
Thu, 20 Jan 2022 15:49:55 +0000 (23:49 +0800)
committerShao-Ce SUN <shaoce@nj.iscas.ac.cn>
Thu, 3 Feb 2022 12:55:47 +0000 (20:55 +0800)
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

llvm/lib/Support/RISCVISAInfo.cpp
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/MCTargetDesc/RISCVInstPrinter.cpp
llvm/lib/Target/RISCV/RISCV.td
llvm/lib/Target/RISCV/RISCVInstrInfo.td
llvm/lib/Target/RISCV/RISCVSubtarget.h
llvm/test/CodeGen/RISCV/attributes.ll
llvm/test/MC/Disassembler/RISCV/unknown-fence-field.txt [deleted file]
llvm/test/MC/RISCV/rv32i-invalid.s
llvm/test/MC/RISCV/rv32zihintpause-valid.s [new file with mode: 0644]
llvm/test/MC/RISCV/rvzihintpause-aliases-valid.s [new file with mode: 0644]

index 2b3395b..a6d4e0b 100644 (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}},
 
index 01f36e6..100e23d 100644 (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();
index 3268740..cfac3f7 100644 (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,
index e32a8fb..f036696 100644 (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)",
index ee6a74b..952910c 100644 (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)>;
index 34c6e8e..7d570a4 100644 (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; }
index ce5b143..b5acd9b 100644 (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"
 ; 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 (file)
index 5b20994..0000000
+++ /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
index 500a0a3..5747512 100644 (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
diff --git a/llvm/test/MC/RISCV/rv32zihintpause-valid.s b/llvm/test/MC/RISCV/rv32zihintpause-valid.s
new file mode 100644 (file)
index 0000000..3ffc387
--- /dev/null
@@ -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 (file)
index 0000000..d505029
--- /dev/null
@@ -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