Skip to content

Commit 42c36da

Browse files
Xinlong-Wutopperc
authored andcommitted
[RISCV] Add MC support of RISCV Zcb Extension
This patch add the instructions of Zcb extension. Instructions in zcb extensions shorten part of bit manipulation instructions. Co-authored-by: Craig Topper <[email protected]> Reviewed By: craig.topper Differential Revision: https://reviews.llvm.org/D131141
1 parent 32ac9db commit 42c36da

17 files changed

+442
-6
lines changed

clang/test/Preprocessor/riscv-target-features.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
// CHECK-NOT: __riscv_svpbmt
4545
// CHECK-NOT: __riscv_svinval
4646
// CHECK-NOT: __riscv_xventanacondops
47+
// CHECK-NOT: __riscv_zca
48+
// CHECK-NOT: __riscv_zcb
4749
// CHECK-NOT: __riscv_zcd
4850
// CHECK-NOT: __riscv_zcf
4951
// CHECK-NOT: __riscv_h
@@ -464,6 +466,19 @@
464466
// RUN: -o - | FileCheck --check-prefix=CHECK-XTHEADVDOT-EXT %s
465467
// CHECK-XTHEADVDOT-EXT: __riscv_xtheadvdot 1000000{{$}}
466468

469+
// RUN: %clang -target riscv32 -march=rv32izca0p70 -menable-experimental-extensions \
470+
// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCA-EXT %s
471+
// RUN: %clang -target riscv64 -march=rv64izca0p70 -menable-experimental-extensions \
472+
// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCA-EXT %s
473+
// CHECK-ZCA-EXT: __riscv_zca 70000{{$}}
474+
475+
// RUN: %clang -target riscv32 -march=rv32izcb0p70 -menable-experimental-extensions \
476+
// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCB-EXT %s
477+
// RUN: %clang -target riscv64 -march=rv64izcb0p70 -menable-experimental-extensions \
478+
// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCB-EXT %s
479+
// CHECK-ZCB-EXT: __riscv_zca 70000{{$}}
480+
// CHECK-ZCB-EXT: __riscv_zcb 70000{{$}}
481+
467482
// RUN: %clang -target riscv32 -march=rv32izcd0p70 -menable-experimental-extensions \
468483
// RUN: -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-ZCD-EXT %s
469484
// RUN: %clang -target riscv64 -march=rv64izcd0p70 -menable-experimental-extensions \

llvm/docs/RISCVUsage.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,9 @@ The primary goal of experimental support is to assist in the process of ratifica
144144
``experimental-zcf``
145145
LLVM implements the `0.70 draft specification <https://github.com/riscv/riscv-code-size-reduction/releases/tag/V0.70.1-TOOLCHAIN-DEV>`_.
146146

147+
``experimental-zcb``
148+
LLVM implements the `0.70 draft specification <https://github.com/riscv/riscv-code-size-reduction/releases/tag/V0.70.1-TOOLCHAIN-DEV>`_.
149+
147150
``experimental-zihintntl``
148151
LLVM implements the `0.2 draft specification <https://github.com/riscv/riscv-isa-manual/releases/tag/draft-20220831-bf5a151>`_.
149152

llvm/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ Changes to the PowerPC Backend
100100
Changes to the RISC-V Backend
101101
-----------------------------
102102

103+
* Assembler support for the Zcb extension was added.
104+
103105
Changes to the WebAssembly Backend
104106
----------------------------------
105107

llvm/lib/Support/RISCVISAInfo.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = {
115115
{"zihintntl", RISCVExtensionVersion{0, 2}},
116116

117117
{"zca", RISCVExtensionVersion{0, 70}},
118+
{"zcb", RISCVExtensionVersion{0, 70}},
118119
{"zcd", RISCVExtensionVersion{0, 70}},
119120
{"zcf", RISCVExtensionVersion{0, 70}},
120121
{"zvfh", RISCVExtensionVersion{0, 1}},
@@ -826,6 +827,7 @@ static const char *ImpliedExtsZkn[] = {"zbkb", "zbkc", "zbkx",
826827
static const char *ImpliedExtsZks[] = {"zbkb", "zbkc", "zbkx", "zksed", "zksh"};
827828
static const char *ImpliedExtsZvfh[] = {"zve32f"};
828829
static const char *ImpliedExtsXTHeadVdot[] = {"v"};
830+
static const char *ImpliedExtsZcb[] = {"zca"};
829831

830832
struct ImpliedExtsEntry {
831833
StringLiteral Name;
@@ -842,6 +844,7 @@ struct ImpliedExtsEntry {
842844
static constexpr ImpliedExtsEntry ImpliedExts[] = {
843845
{{"v"}, {ImpliedExtsV}},
844846
{{"xtheadvdot"}, {ImpliedExtsXTHeadVdot}},
847+
{{"zcb"}, {ImpliedExtsZcb}},
845848
{{"zdinx"}, {ImpliedExtsZdinx}},
846849
{{"zfh"}, {ImpliedExtsZfh}},
847850
{{"zfhmin"}, {ImpliedExtsZfhmin}},

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,16 @@ struct RISCVOperand : public MCParsedAsmOperand {
618618
VK == RISCVMCExpr::VK_RISCV_None;
619619
}
620620

621+
bool isUImm2Lsb0() const {
622+
if (!isImm())
623+
return false;
624+
int64_t Imm;
625+
RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
626+
bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
627+
return IsConstantImm && isShiftedUInt<1, 1>(Imm) &&
628+
VK == RISCVMCExpr::VK_RISCV_None;
629+
}
630+
621631
bool isUImm7Lsb00() const {
622632
if (!isImm())
623633
return false;
@@ -1151,6 +1161,9 @@ bool RISCVAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
11511161
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 4) - 1);
11521162
case Match_InvalidUImm2:
11531163
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 2) - 1);
1164+
case Match_InvalidUImm2Lsb0:
1165+
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, 2,
1166+
"immediate must be one of");
11541167
case Match_InvalidUImm3:
11551168
return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << 3) - 1);
11561169
case Match_InvalidUImm5:

llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ enum {
4343
InstFormatCA = 14,
4444
InstFormatCB = 15,
4545
InstFormatCJ = 16,
46-
InstFormatOther = 17,
46+
InstFormatCSZN = 17,
47+
InstFormatOther = 18,
4748

4849
InstFormatMask = 31,
4950
InstFormatShift = 0,
@@ -234,6 +235,7 @@ namespace RISCVOp {
234235
enum OperandType : unsigned {
235236
OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET,
236237
OPERAND_UIMM2 = OPERAND_FIRST_RISCV_IMM,
238+
OPERAND_UIMM2_LSB0,
237239
OPERAND_UIMM3,
238240
OPERAND_UIMM4,
239241
OPERAND_UIMM5,

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,14 @@ def HasStdExtCOrZca
299299
"'Zca' (part of the C extension, excluding "
300300
"compressed floating point loads/stores)">;
301301

302+
def FeatureExtZcb
303+
: SubtargetFeature<"experimental-zcb", "HasStdExtZcb", "true",
304+
"'Zcb' (Compressed basic bit manipulation instructions)",
305+
[FeatureExtZca]>;
306+
def HasStdExtZcb : Predicate<"Subtarget->hasStdExtZcb()">,
307+
AssemblerPredicate<(all_of FeatureExtZcb),
308+
"'Zcb' (Compressed basic bit manipulation instructions)">;
309+
302310
def FeatureExtZcd
303311
: SubtargetFeature<"experimental-zcd", "HasStdExtZcd", "true",
304312
"'Zcd' (Compressed Double-Precision Floating-Point Instructions)">;

llvm/lib/Target/RISCV/RISCVInstrFormats.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ def InstFormatCS : InstFormat<13>;
4747
def InstFormatCA : InstFormat<14>;
4848
def InstFormatCB : InstFormat<15>;
4949
def InstFormatCJ : InstFormat<16>;
50-
def InstFormatOther : InstFormat<17>;
50+
def InstFormatCSZN : InstFormat<17>;
51+
def InstFormatOther : InstFormat<18>;
5152

5253
class RISCVVConstraint<bits<3> val> {
5354
bits<3> Value = val;

llvm/lib/Target/RISCV/RISCVInstrFormatsC.td

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,14 @@ class RVInst16CJ<bits<3> funct3, bits<2> opcode, dag outs, dag ins,
157157
let Inst{2} = offset{4};
158158
let Inst{1-0} = opcode;
159159
}
160+
161+
class RVInst16CSZN<bits<6> funct6, bits<5> funct5, bits<2> opcode, dag outs,
162+
dag ins, string opcodestr, string argstr>
163+
: RVInst16<outs, ins, opcodestr, argstr, [], InstFormatCSZN>{
164+
bits<3> rd;
165+
166+
let Inst{15-10} = funct6;
167+
let Inst{9-7} = rd;
168+
let Inst{6-2} = funct5;
169+
let Inst{1-0} = opcode;
170+
}

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,6 +1620,12 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
16201620
CASE_OPERAND_UIMM(4)
16211621
CASE_OPERAND_UIMM(5)
16221622
CASE_OPERAND_UIMM(7)
1623+
CASE_OPERAND_UIMM(12)
1624+
CASE_OPERAND_UIMM(20)
1625+
// clang-format on
1626+
case RISCVOp::OPERAND_UIMM2_LSB0:
1627+
Ok = isShiftedUInt<1, 1>(Imm);
1628+
break;
16231629
case RISCVOp::OPERAND_UIMM7_LSB00:
16241630
Ok = isShiftedUInt<5, 2>(Imm);
16251631
break;
@@ -1629,9 +1635,6 @@ bool RISCVInstrInfo::verifyInstruction(const MachineInstr &MI,
16291635
case RISCVOp::OPERAND_UIMM8_LSB000:
16301636
Ok = isShiftedUInt<5, 3>(Imm);
16311637
break;
1632-
CASE_OPERAND_UIMM(12)
1633-
CASE_OPERAND_UIMM(20)
1634-
// clang-format on
16351638
case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
16361639
Ok = isShiftedInt<6, 4>(Imm) && (Imm != 0);
16371640
break;

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,17 @@ def uimmlog2xlen : Operand<XLenVT>, ImmLeaf<XLenVT, [{
191191
let OperandNamespace = "RISCVOp";
192192
}
193193

194-
def uimm2 : Operand<XLenVT> {
194+
def uimm2 : Operand<XLenVT>, ImmLeaf<XLenVT, [{return isUInt<2>(Imm);}]> {
195195
let ParserMatchClass = UImmAsmOperand<2>;
196196
let DecoderMethod = "decodeUImmOperand<2>";
197197
let OperandType = "OPERAND_UIMM2";
198198
let OperandNamespace = "RISCVOp";
199+
let MCOperandPredicate = [{
200+
int64_t Imm;
201+
if (!MCOp.evaluateAsConstantImm(Imm))
202+
return false;
203+
return isUInt<2>(Imm);
204+
}];
199205
}
200206

201207
def uimm3 : Operand<XLenVT> {
@@ -1853,6 +1859,7 @@ include "RISCVInstrInfoF.td"
18531859
include "RISCVInstrInfoD.td"
18541860
include "RISCVInstrInfoC.td"
18551861
include "RISCVInstrInfoZb.td"
1862+
include "RISCVInstrInfoZc.td"
18561863
include "RISCVInstrInfoZk.td"
18571864
include "RISCVInstrInfoV.td"
18581865
include "RISCVInstrInfoZfh.td"
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
//===-- RISCVInstrInfoZc.td - RISC-V 'Zc*' instructions ----*- tablegen -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// This file describes the RISC-V instructions from the 'Zc*' compressed
10+
/// instruction extensions, version 0.70.4.
11+
/// This version is still experimental as the 'Zc*' extensions haven't been
12+
/// ratified yet.
13+
///
14+
//===----------------------------------------------------------------------===//
15+
16+
//===----------------------------------------------------------------------===//
17+
// Operand and SDNode transformation definitions.
18+
//===----------------------------------------------------------------------===//
19+
20+
def uimm2_lsb0 : Operand<XLenVT>,
21+
ImmLeaf<XLenVT, [{return isShiftedUInt<1, 1>(Imm);}]> {
22+
let ParserMatchClass = UImmAsmOperand<2, "Lsb0">;
23+
let EncoderMethod = "getImmOpValue";
24+
let DecoderMethod = "decodeUImmOperand<2>";
25+
let OperandType = "OPERAND_UIMM2_LSB0";
26+
let OperandNamespace = "RISCVOp";
27+
let MCOperandPredicate = [{
28+
int64_t Imm;
29+
if (!MCOp.evaluateAsConstantImm(Imm))
30+
return false;
31+
return isShiftedUInt<1, 1>(Imm);
32+
}];
33+
}
34+
35+
//===----------------------------------------------------------------------===//
36+
// Instruction Class Templates
37+
//===----------------------------------------------------------------------===//
38+
39+
let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in
40+
class RVZcArith_r<bits<5> funct5, string OpcodeStr> :
41+
RVInst16CSZN<0b100111, funct5, 0b01, (outs GPRC:$rd_wb), (ins GPRC:$rd),
42+
OpcodeStr, "$rd"> {
43+
let Constraints = "$rd = $rd_wb";
44+
}
45+
46+
//===----------------------------------------------------------------------===//
47+
// Instructions
48+
//===----------------------------------------------------------------------===//
49+
50+
let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in
51+
def C_ZEXT_W : RVZcArith_r<0b11100 , "c.zext.w">,
52+
Sched<[WriteIALU32, ReadIALU32, ReadIALU32]>;
53+
54+
let Predicates = [HasStdExtZcb, HasStdExtZbb] in {
55+
def C_ZEXT_H : RVZcArith_r<0b11010 , "c.zext.h">,
56+
Sched<[WriteIALU, ReadIALU]>;
57+
def C_SEXT_B : RVZcArith_r<0b11001 , "c.sext.b">,
58+
Sched<[WriteIALU, ReadIALU]>;
59+
def C_SEXT_H : RVZcArith_r<0b11011 , "c.sext.h">,
60+
Sched<[WriteIALU, ReadIALU]>;
61+
}
62+
63+
let Predicates = [HasStdExtZcb] in
64+
def C_ZEXT_B : RVZcArith_r<0b11000 , "c.zext.b">,
65+
Sched<[WriteIALU, ReadIALU]>;
66+
67+
let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in
68+
def C_MUL : CA_ALU<0b100111, 0b10, "c.mul", GPRC>,
69+
Sched<[WriteIMul, ReadIMul, ReadIMul]>;
70+
71+
let Predicates = [HasStdExtZcb] in {
72+
def C_NOT : RVZcArith_r<0b11101 , "c.not">,
73+
Sched<[WriteIALU, ReadIALU]>;
74+
75+
def C_LBU : CLoad_ri<0b100, "c.lbu", GPRC, uimm2>,
76+
Sched<[WriteLDB, ReadMemBase]> {
77+
bits<2> imm;
78+
79+
let Inst{12-10} = 0b000;
80+
let Inst{6-5} = imm{0,1};
81+
}
82+
83+
def C_LHU : CLoad_ri<0b100, "c.lhu", GPRC, uimm2_lsb0>,
84+
Sched<[WriteLDH, ReadMemBase]> {
85+
bits<2> imm;
86+
87+
let Inst{12-10} = 0b001;
88+
let Inst{6} = 0b0;
89+
let Inst{5} = imm{1};
90+
}
91+
92+
def C_LH : CLoad_ri<0b100, "c.lh", GPRC, uimm2_lsb0>,
93+
Sched<[WriteLDH, ReadMemBase]> {
94+
bits<2> imm;
95+
96+
let Inst{12-10} = 0b001;
97+
let Inst{6} = 0b1;
98+
let Inst{5} = imm{1};
99+
}
100+
101+
def C_SB : CStore_rri<0b100, "c.sb", GPRC, uimm2>,
102+
Sched<[WriteSTB, ReadStoreData, ReadMemBase]> {
103+
bits<2> imm;
104+
105+
let Inst{12-10} = 0b010;
106+
let Inst{6-5} = imm{0,1};
107+
}
108+
109+
def C_SH : CStore_rri<0b100, "c.sh", GPRC, uimm2_lsb0>,
110+
Sched<[WriteSTH, ReadStoreData, ReadMemBase]> {
111+
bits<2> imm;
112+
113+
let Inst{12-10} = 0b011;
114+
let Inst{6} = 0b1;
115+
let Inst{5} = imm{1};
116+
}
117+
}
118+
119+
let Predicates = [HasStdExtZcb, HasStdExtMOrZmmul] in{
120+
def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs1, GPRC:$rs2),
121+
(C_MUL GPRC:$rs1, GPRC:$rs2)>;
122+
let isCompressOnly = true in
123+
def : CompressPat<(MUL GPRC:$rs1, GPRC:$rs2, GPRC:$rs1),
124+
(C_MUL GPRC:$rs1, GPRC:$rs2)>;
125+
} // Predicates = [HasStdExtZcb, HasStdExtMOrZmmul]
126+
127+
let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
128+
def : CompressPat<(SEXT_B GPRC:$rs1, GPRC:$rs1),
129+
(C_SEXT_B GPRC:$rs1, GPRC:$rs1)>;
130+
def : CompressPat<(SEXT_H GPRC:$rs1, GPRC:$rs1),
131+
(C_SEXT_H GPRC:$rs1, GPRC:$rs1)>;
132+
} // Predicates = [HasStdExtZcb, HasStdExtZbb]
133+
134+
let Predicates = [HasStdExtZcb, HasStdExtZbb] in{
135+
def : CompressPat<(ZEXT_H_RV32 GPRC:$rs1, GPRC:$rs1),
136+
(C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
137+
def : CompressPat<(ZEXT_H_RV64 GPRC:$rs1, GPRC:$rs1),
138+
(C_ZEXT_H GPRC:$rs1, GPRC:$rs1)>;
139+
} // Predicates = [HasStdExtZcb, HasStdExtZbb]
140+
141+
let Predicates = [HasStdExtZcb] in{
142+
def : CompressPat<(ANDI GPRC:$rs1, GPRC:$rs1, 255),
143+
(C_ZEXT_B GPRC:$rs1, GPRC:$rs1)>;
144+
} // Predicates = [HasStdExtZcb]
145+
146+
let Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64] in{
147+
def : CompressPat<(ADD_UW GPRC:$rs1, GPRC:$rs1, X0),
148+
(C_ZEXT_W GPRC:$rs1, GPRC:$rs1)>;
149+
} // Predicates = [HasStdExtZcb, HasStdExtZba, IsRV64]
150+
151+
let Predicates = [HasStdExtZcb] in{
152+
def : CompressPat<(XORI GPRC:$rs1, GPRC:$rs1, -1),
153+
(C_NOT GPRC:$rs1, GPRC:$rs1)>;
154+
}
155+
156+
let Predicates = [HasStdExtZcb] in{
157+
def : CompressPat<(LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm),
158+
(C_LBU GPRC:$rd, GPRCMem:$rs1, uimm2:$imm)>;
159+
def : CompressPat<(LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
160+
(C_LHU GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
161+
def : CompressPat<(LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm),
162+
(C_LH GPRC:$rd, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
163+
def : CompressPat<(SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm),
164+
(C_SB GPRC:$rs2, GPRCMem:$rs1, uimm2:$imm)>;
165+
def : CompressPat<(SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm),
166+
(C_SH GPRC:$rs2, GPRCMem:$rs1, uimm2_lsb0:$imm)>;
167+
}// Predicates = [HasStdExtZcb]
168+
169+
170+
//===----------------------------------------------------------------------===//
171+
// Pseudo Instructions
172+
//===----------------------------------------------------------------------===//
173+
174+
let Predicates = [HasStdExtZcb] in {
175+
def : InstAlias<"c.lbu $rd, (${rs1})",(C_LBU GPRC:$rd, GPRC:$rs1, 0)>;
176+
def : InstAlias<"c.lhu $rd, (${rs1})",(C_LHU GPRC:$rd, GPRC:$rs1, 0)>;
177+
def : InstAlias<"c.lh $rd, (${rs1})", (C_LH GPRC:$rd, GPRC:$rs1, 0)>;
178+
def : InstAlias<"c.sb $rd, (${rs1})", (C_SB GPRC:$rd, GPRC:$rs1, 0)>;
179+
def : InstAlias<"c.sh $rd, (${rs1})", (C_SH GPRC:$rd, GPRC:$rs1, 0)>;
180+
}

0 commit comments

Comments
 (0)