[llvm] riscv: Added Zvinsert instructions (PR #92262)

Abel Bernabeu via llvm-commits llvm-commits at lists.llvm.org
Wed May 15 06:49:41 PDT 2024


https://github.com/abel-bernabeu created https://github.com/llvm/llvm-project/pull/92262

The Zvinsert optional extension for Zv enables data movement between integer scalar registers and arbitrary elements of a vector register.

The implementers of this extension provide a convenient alternative to spilling scalar registers to memory, using vector registers as alternative storage for saving and restoring scalar registers.

More patches exploiting the new possibilities in LLVM should come soon.

>From 19e7f413ef1dd64e012de793dba988c5a774a6df Mon Sep 17 00:00:00 2001
From: Abel Bernabeu <abel.bernabeu at esperantotech.com>
Date: Wed, 15 May 2024 00:57:19 +0200
Subject: [PATCH] riscv: Added Zvinsert instructions

The Zvinsert optional extension for Zv enables data movement between
integer scalar registers and arbitrary elements of a vector register.

The implementers of this extension provide a convenient alternative
to spilling scalar registers to memory, using vector registers as
alternative storage for saving and restoring scalar registers.

More patches exploiting the new possibilities in LLVM should come
soon.
---
 .../RISCV/Disassembler/RISCVDisassembler.cpp  |   3 +
 llvm/lib/Target/RISCV/RISCVFeatures.td        |   8 ++
 llvm/lib/Target/RISCV/RISCVInstrInfoV.td      |   1 +
 .../Target/RISCV/RISCVInstrInfoZvinsert.td    | 130 ++++++++++++++++++
 llvm/test/MC/RISCV/rvzvinsert-valid.s         |  18 +++
 5 files changed, 160 insertions(+)
 create mode 100644 llvm/lib/Target/RISCV/RISCVInstrInfoZvinsert.td
 create mode 100644 llvm/test/MC/RISCV/rvzvinsert-valid.s

diff --git a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
index b9e8e1f33d3ae..674cce659902f 100644
--- a/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
+++ b/llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
@@ -531,6 +531,7 @@ void RISCVDisassembler::addSPOperands(MCInst &MI) const {
 #define TRY_TO_DECODE_FEATURE(FEATURE, DECODER_TABLE, DESC)                    \
   TRY_TO_DECODE(STI.hasFeature(FEATURE), DECODER_TABLE, DESC)
 
+
 DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
                                                  ArrayRef<uint8_t> Bytes,
                                                  uint64_t Address,
@@ -553,6 +554,8 @@ DecodeStatus RISCVDisassembler::getInstruction32(MCInst &MI, uint64_t &Size,
                 "RV32Zacas table (Compare-And-Swap and rv32)");
   TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZfinx, DecoderTableRVZfinx32,
                         "RVZfinx table (Float in Integer)");
+  TRY_TO_DECODE_FEATURE(RISCV::FeatureStdExtZvinsert, DecoderTableRVZvinsert32,
+                        "RVZvinsert table (Moves between Scalars and Vector Elements)");
   TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXVentanaCondOps,
                         DecoderTableXVentana32, "Ventana custom opcode table");
   TRY_TO_DECODE_FEATURE(RISCV::FeatureVendorXTHeadBa, DecoderTableXTHeadBa32,
diff --git a/llvm/lib/Target/RISCV/RISCVFeatures.td b/llvm/lib/Target/RISCV/RISCVFeatures.td
index 89e1214f469da..05183283aa8e2 100644
--- a/llvm/lib/Target/RISCV/RISCVFeatures.td
+++ b/llvm/lib/Target/RISCV/RISCVFeatures.td
@@ -790,6 +790,14 @@ def FeatureStdExtZvksg
                      "'Zvksg' (shorthand for 'Zvks' and 'Zvkg')",
                      [FeatureStdExtZvks, FeatureStdExtZvkg]>;
 
+def FeatureStdExtZvinsert
+    : SubtargetFeature<"zvinsert", "HasStdExtZvinsert", "true",
+                       "'Zvinsert' (Vector Extension for Moves between Scalars and Vector Elements)">;
+
+def HasStdExtZvinsert : Predicate<"Subtarget->hasStdExtZvinsert()">,
+      AssemblerPredicate<(any_of FeatureStdExtZvinsert),
+                         "'Zvinsert' (Vector Extension for Moves between Scalars and Vector Elements)">;
+
 // Vector instruction predicates
 
 def HasVInstructions    : Predicate<"Subtarget->hasVInstructions()">,
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td
index e68fb42ece9f0..9d2908d52f3a3 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoV.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoV.td
@@ -1789,4 +1789,5 @@ let Predicates = [HasVInstructionsI64, IsRV64] in {
 } // Predicates = [HasVInstructionsI64, IsRV64]
 
 include "RISCVInstrInfoZvfbf.td"
+include "RISCVInstrInfoZvinsert.td"
 include "RISCVInstrInfoVPseudos.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZvinsert.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZvinsert.td
new file mode 100644
index 0000000000000..517c834c63ca5
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZvinsert.td
@@ -0,0 +1,130 @@
+//===- RISCVInstrInfoZvinsert.td - RISC-V 'Zvinsert' instructions ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the RISC-V V instructions from the standard 'Zvinsert',
+// Vector Extension for Moves between Scalars and Vector Elements, version 0.94.
+//
+//===----------------------------------------------------------------------===//
+
+class RVStdExtZvinsertInst<
+  dag outs, dag ins, string opcodestr, string argstr> :
+  RVInst<outs, ins, opcodestr, argstr, [], InstFormatR> {
+  let mayLoad = 0;
+  let mayStore = 0;
+  let hasSideEffects = 0;
+  let DecoderNamespace = "RVZvinsert";
+  let Predicates = [HasStdExtZvinsert];
+}
+
+//===----------------------------------------------------------------------===//
+// INSERTI.S.X
+//===----------------------------------------------------------------------===//
+
+class RVStdExtZvinsertInstINSERTI<
+  dag outs, dag ins, string opcodestr, string argstr> :
+  RVStdExtZvinsertInst<outs, ins, opcodestr, argstr> {
+
+  bits<5> rs2;
+  bits<5> imm;
+  bits<5> vd;
+
+  let Inst{31-26} = 0b010100;
+  let Inst{25} = 0;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = imm;
+  let Inst{14-12} = OPIVI.Value;
+  let Inst{11-7} = vd;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+class VINSERTI<string opcodestr>
+    : RVStdExtZvinsertInstINSERTI<(outs VR:$vd), (ins GPR:$rs2, uimm5:$imm),
+              opcodestr, "${vd}, ${rs2}, ${imm}">;
+
+def VINSERTI : VINSERTI<"vinserti.s.x">;
+
+//===----------------------------------------------------------------------===//
+// INSERT.S.X
+//===----------------------------------------------------------------------===//
+
+class RVStdExtZvinsertInstINSERT<
+  dag outs, dag ins, string opcodestr, string argstr> :
+  RVStdExtZvinsertInst<outs, ins, opcodestr, argstr> {
+
+  bits<5> rs2;
+  bits<5> rs1;
+  bits<5> vd;
+
+  let Inst{31-26} = 0b010100;
+  let Inst{25} = 0;
+  let Inst{24-20} = rs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPIVX.Value;
+  let Inst{11-7} = vd;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+class VINSERT<string opcodestr>
+    : RVStdExtZvinsertInstINSERT<(outs VR:$vd), (ins GPR:$rs2, GPR:$rs1),
+              opcodestr, "${vd}, ${rs2}, (${rs1})">;
+
+def VINSERT : VINSERT<"vinsert.s.x">;
+
+//===----------------------------------------------------------------------===//
+// EXTRACTI.S.X
+//===----------------------------------------------------------------------===//
+
+class RVStdExtZvinsertInstEXTRACTI<
+  dag outs, dag ins, string opcodestr, string argstr> :
+  RVStdExtZvinsertInst<outs, ins, opcodestr, argstr> {
+
+  bits<5> vs2;
+  bits<5> imm;
+  bits<5> rd;
+
+  let Inst{31-26} = 0b010101;
+  let Inst{25} = 0;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = imm;
+  let Inst{14-12} = OPIVI.Value;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+class VEXTRACTI<string opcodestr>
+    : RVStdExtZvinsertInstEXTRACTI<(outs GPR:$rd), (ins VR:$vs2, uimm5:$imm),
+              opcodestr, "${rd}, ${vs2}, ${imm}">;
+
+def VEXTRACTI : VEXTRACTI<"vextracti.x.s">;
+
+//===----------------------------------------------------------------------===//
+// EXTRACT.S.X
+//===----------------------------------------------------------------------===//
+
+class RVStdExtZvinsertInstEXTRACT<
+  dag outs, dag ins, string opcodestr, string argstr> :
+  RVStdExtZvinsertInst<outs, ins, opcodestr, argstr> {
+
+  bits<5> vs2;
+  bits<5> rs1;
+  bits<5> rd;
+
+  let Inst{31-26} = 0b010101;
+  let Inst{25} = 0;
+  let Inst{24-20} = vs2;
+  let Inst{19-15} = rs1;
+  let Inst{14-12} = OPIVX.Value;
+  let Inst{11-7} = rd;
+  let Inst{6-0} = OPC_OP_V.Value;
+}
+
+class VEXTRACT<string opcodestr>
+    : RVStdExtZvinsertInstEXTRACT<(outs GPR:$rd), (ins VR:$vs2, GPR:$rs1),
+              opcodestr, "${rd}, ${vs2}, (${rs1})">;
+
+def VEXTRACT : VEXTRACT<"vextract.x.s">;
\ No newline at end of file
diff --git a/llvm/test/MC/RISCV/rvzvinsert-valid.s b/llvm/test/MC/RISCV/rvzvinsert-valid.s
new file mode 100644
index 0000000000000..97a2e1cb73b9d
--- /dev/null
+++ b/llvm/test/MC/RISCV/rvzvinsert-valid.s
@@ -0,0 +1,18 @@
+# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+zvinsert -show-encoding %s | \
+# RUN:     llvm-objdump -d --mattr=+zvinsert -M no-aliases -M numeric - | \
+# RUN:     FileCheck -check-prefixes=CHECK %s
+# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+zvinsert -show-encoding %s | \
+# RUN:     llvm-objdump -d --mattr=+zvinsert -M no-aliases -M numeric - | \
+# RUN:     FileCheck -check-prefixes=CHECK %s
+
+# CHECK: 501fb1d7      vinserti.s.x    v3, x1, 0x1f
+vinserti.s.x v3, x1, 31
+
+# CHECK: 5013c1d7      vinsert.s.x     v3, x1, (x7)
+vinsert.s.x v3, x1, (x7)
+
+# CHECK: 547fb1d7      vextracti.x.s   x3, v7, 0x1f
+vextracti.x.s x3, v7, 31
+
+# CHECK: 5453c1d7      vextract.x.s    x3, v5, (x7)
+vextract.x.s x3, v5, (x7)
\ No newline at end of file



More information about the llvm-commits mailing list