Skip to content

Commit 11857be

Browse files
authored
[RISCV] Add basic ISel patterns for Xqcisls instructions (#135918)
This patch adds basic instruction selection patterns for generating the scaled load/store instructions that are a part of the Qualcomm uC Xqcisls vendor extension.
1 parent bf0de88 commit 11857be

File tree

3 files changed

+236
-1
lines changed

3 files changed

+236
-1
lines changed

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def InsnDirectiveOpcode : AsmOperandClass {
248248

249249
def uimm1 : RISCVUImmLeafOp<1>;
250250
def uimm2 : RISCVUImmLeafOp<2>;
251-
def uimm3 : RISCVUImmOp<3>;
251+
def uimm3 : RISCVUImmLeafOp<3>;
252252
def uimm4 : RISCVUImmLeafOp<4>;
253253
def uimm5 : RISCVUImmLeafOp<5>;
254254
def uimm6 : RISCVUImmLeafOp<6>;

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,9 @@ def AddLike: PatFrags<(ops node:$A, node:$B),
164164
return CurDAG->isBaseWithConstantOffset(SDValue(N, 0));
165165
}]>;
166166

167+
def AddShl : PatFrag<(ops node:$Ra, node:$Rb, node:$SH3),
168+
(add node:$Ra, (shl node:$Rb, node:$SH3))>;
169+
167170
//===----------------------------------------------------------------------===//
168171
// Instruction Formats
169172
//===----------------------------------------------------------------------===//
@@ -1252,6 +1255,14 @@ class QC48StPat<PatFrag StoreOp, RVInst48 Inst>
12521255
: Pat<(StoreOp (i32 GPR:$rs2), (AddLike (i32 GPR:$rs1), simm26_nosimm12:$imm26)),
12531256
(Inst GPR:$rs2, GPR:$rs1, simm26_nosimm12:$imm26)>;
12541257

1258+
class QCScaledLdPat<PatFrag LoadOp, RVInst Inst>
1259+
: Pat<(i32 (LoadOp (AddShl (i32 GPRMem:$rs1), (i32 GPRNoX0:$rs2), uimm3:$shamt))),
1260+
(Inst GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt)>;
1261+
1262+
class QCScaledStPat<PatFrag StoreOp, RVInst Inst>
1263+
: Pat<(StoreOp (i32 GPR:$rd), (AddShl (i32 GPRMem:$rs1), (i32 GPRNoX0:$rs2), uimm3:$shamt)),
1264+
(Inst GPR:$rd, GPRMem:$rs1, GPRNoX0:$rs2, uimm3:$shamt)>;
1265+
12551266
/// Simple arithmetic operations
12561267

12571268
let Predicates = [HasVendorXqcilia, IsRV32] in {
@@ -1266,6 +1277,8 @@ def : PatGprNoX0Simm26NoSimm12<or, QC_E_ORI>;
12661277
def : PatGprNoX0Simm26NoSimm12<xor, QC_E_XORI>;
12671278
} // Predicates = [HasVendorXqcilia, IsRV32]
12681279

1280+
/// Load/Store operations
1281+
12691282
let Predicates = [HasVendorXqcilo, IsRV32], AddedComplexity = 2 in {
12701283
def : QC48LdPat<sextloadi8, QC_E_LB>;
12711284
def : QC48LdPat<extloadi8, QC_E_LBU>; // Prefer unsigned due to no c.lb in Zcb.
@@ -1280,5 +1293,20 @@ let Predicates = [HasVendorXqcilo, IsRV32], AddedComplexity = 2 in {
12801293
def : QC48StPat<store, QC_E_SW>;
12811294
} // Predicates = [HasVendorXqcilo, IsRV32], AddedComplexity = 2
12821295

1296+
1297+
let Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1 in {
1298+
def : QCScaledLdPat<sextloadi8, QC_LRB>;
1299+
def : QCScaledLdPat<extloadi8, QC_LRBU>;
1300+
def : QCScaledLdPat<sextloadi16, QC_LRH>;
1301+
def : QCScaledLdPat<extloadi16, QC_LRH>;
1302+
def : QCScaledLdPat<load, QC_LRW>;
1303+
def : QCScaledLdPat<zextloadi8, QC_LRBU>;
1304+
def : QCScaledLdPat<zextloadi16, QC_LRHU>;
1305+
1306+
def : QCScaledStPat<truncstorei8, QC_SRB>;
1307+
def : QCScaledStPat<truncstorei16, QC_SRH>;
1308+
def : QCScaledStPat<store, QC_SRW>;
1309+
} // Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1
1310+
12831311
let Predicates = [HasVendorXqciint, IsRV32] in
12841312
def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;

llvm/test/CodeGen/RISCV/xqcisls.ll

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s -check-prefixes=RV32I
4+
; RUN: llc -mtriple=riscv32 --mattr=+zba -verify-machineinstrs < %s \
5+
; RUN: | FileCheck %s -check-prefixes=RV32IZBA
6+
; RUN: llc -mtriple=riscv32 -mattr=+zba,+experimental-xqcisls -verify-machineinstrs < %s \
7+
; RUN: | FileCheck %s -check-prefixes=RV32IZBAXQCISLS
8+
9+
define i32 @lb_ri(i8* %a, i32 %b) {
10+
; RV32I-LABEL: lb_ri:
11+
; RV32I: # %bb.0:
12+
; RV32I-NEXT: slli a1, a1, 3
13+
; RV32I-NEXT: add a0, a0, a1
14+
; RV32I-NEXT: lb a0, 0(a0)
15+
; RV32I-NEXT: ret
16+
;
17+
; RV32IZBA-LABEL: lb_ri:
18+
; RV32IZBA: # %bb.0:
19+
; RV32IZBA-NEXT: sh3add a0, a1, a0
20+
; RV32IZBA-NEXT: lb a0, 0(a0)
21+
; RV32IZBA-NEXT: ret
22+
;
23+
; RV32IZBAXQCISLS-LABEL: lb_ri:
24+
; RV32IZBAXQCISLS: # %bb.0:
25+
; RV32IZBAXQCISLS-NEXT: qc.lrb a0, a0, a1, 3
26+
; RV32IZBAXQCISLS-NEXT: ret
27+
%shl = shl i32 %b, 3
28+
%1 = getelementptr i8, i8* %a, i32 %shl
29+
%2 = load i8, i8* %1
30+
%3 = sext i8 %2 to i32
31+
ret i32 %3
32+
}
33+
34+
define i32 @lbu_ri(i8* %a, i32 %b) {
35+
; RV32I-LABEL: lbu_ri:
36+
; RV32I: # %bb.0:
37+
; RV32I-NEXT: slli a1, a1, 2
38+
; RV32I-NEXT: add a0, a0, a1
39+
; RV32I-NEXT: lbu a0, 0(a0)
40+
; RV32I-NEXT: ret
41+
;
42+
; RV32IZBA-LABEL: lbu_ri:
43+
; RV32IZBA: # %bb.0:
44+
; RV32IZBA-NEXT: sh2add a0, a1, a0
45+
; RV32IZBA-NEXT: lbu a0, 0(a0)
46+
; RV32IZBA-NEXT: ret
47+
;
48+
; RV32IZBAXQCISLS-LABEL: lbu_ri:
49+
; RV32IZBAXQCISLS: # %bb.0:
50+
; RV32IZBAXQCISLS-NEXT: qc.lrbu a0, a0, a1, 2
51+
; RV32IZBAXQCISLS-NEXT: ret
52+
%shl = shl i32 %b, 2
53+
%1 = getelementptr i8, i8* %a, i32 %shl
54+
%2 = load i8, i8* %1
55+
%3 = zext i8 %2 to i32
56+
ret i32 %3
57+
}
58+
59+
define i32 @lh_ri(i16* %a, i32 %b) {
60+
; RV32I-LABEL: lh_ri:
61+
; RV32I: # %bb.0:
62+
; RV32I-NEXT: slli a1, a1, 5
63+
; RV32I-NEXT: add a0, a0, a1
64+
; RV32I-NEXT: lh a0, 0(a0)
65+
; RV32I-NEXT: ret
66+
;
67+
; RV32IZBA-LABEL: lh_ri:
68+
; RV32IZBA: # %bb.0:
69+
; RV32IZBA-NEXT: slli a1, a1, 5
70+
; RV32IZBA-NEXT: add a0, a0, a1
71+
; RV32IZBA-NEXT: lh a0, 0(a0)
72+
; RV32IZBA-NEXT: ret
73+
;
74+
; RV32IZBAXQCISLS-LABEL: lh_ri:
75+
; RV32IZBAXQCISLS: # %bb.0:
76+
; RV32IZBAXQCISLS-NEXT: qc.lrh a0, a0, a1, 5
77+
; RV32IZBAXQCISLS-NEXT: ret
78+
%shl = shl i32 %b, 4
79+
%1 = getelementptr i16, i16* %a, i32 %shl
80+
%2 = load i16, i16* %1
81+
%3 = sext i16 %2 to i32
82+
ret i32 %3
83+
}
84+
85+
define i32 @lhu_ri(i16* %a, i32 %b) {
86+
; RV32I-LABEL: lhu_ri:
87+
; RV32I: # %bb.0:
88+
; RV32I-NEXT: slli a1, a1, 6
89+
; RV32I-NEXT: add a0, a0, a1
90+
; RV32I-NEXT: lhu a0, 0(a0)
91+
; RV32I-NEXT: ret
92+
;
93+
; RV32IZBA-LABEL: lhu_ri:
94+
; RV32IZBA: # %bb.0:
95+
; RV32IZBA-NEXT: slli a1, a1, 6
96+
; RV32IZBA-NEXT: add a0, a0, a1
97+
; RV32IZBA-NEXT: lhu a0, 0(a0)
98+
; RV32IZBA-NEXT: ret
99+
;
100+
; RV32IZBAXQCISLS-LABEL: lhu_ri:
101+
; RV32IZBAXQCISLS: # %bb.0:
102+
; RV32IZBAXQCISLS-NEXT: qc.lrhu a0, a0, a1, 6
103+
; RV32IZBAXQCISLS-NEXT: ret
104+
%shl = shl i32 %b, 5
105+
%1 = getelementptr i16, i16* %a, i32 %shl
106+
%2 = load i16, i16* %1
107+
%3 = zext i16 %2 to i32
108+
ret i32 %3
109+
}
110+
111+
define i32 @lw_ri(i32* %a, i32 %b) {
112+
; RV32I-LABEL: lw_ri:
113+
; RV32I: # %bb.0:
114+
; RV32I-NEXT: slli a1, a1, 6
115+
; RV32I-NEXT: add a0, a0, a1
116+
; RV32I-NEXT: lw a0, 0(a0)
117+
; RV32I-NEXT: ret
118+
;
119+
; RV32IZBA-LABEL: lw_ri:
120+
; RV32IZBA: # %bb.0:
121+
; RV32IZBA-NEXT: slli a1, a1, 6
122+
; RV32IZBA-NEXT: add a0, a0, a1
123+
; RV32IZBA-NEXT: lw a0, 0(a0)
124+
; RV32IZBA-NEXT: ret
125+
;
126+
; RV32IZBAXQCISLS-LABEL: lw_ri:
127+
; RV32IZBAXQCISLS: # %bb.0:
128+
; RV32IZBAXQCISLS-NEXT: qc.lrw a0, a0, a1, 6
129+
; RV32IZBAXQCISLS-NEXT: ret
130+
%shl = shl i32 %b, 4
131+
%1 = getelementptr i32, i32* %a, i32 %shl
132+
%2 = load i32, i32* %1
133+
ret i32 %2
134+
}
135+
136+
define void @sb_ri(i8* %a, i8 %b, i32 %c) {
137+
; RV32I-LABEL: sb_ri:
138+
; RV32I: # %bb.0:
139+
; RV32I-NEXT: slli a2, a2, 7
140+
; RV32I-NEXT: add a0, a0, a2
141+
; RV32I-NEXT: sb a1, 0(a0)
142+
; RV32I-NEXT: ret
143+
;
144+
; RV32IZBA-LABEL: sb_ri:
145+
; RV32IZBA: # %bb.0:
146+
; RV32IZBA-NEXT: slli a2, a2, 7
147+
; RV32IZBA-NEXT: add a0, a0, a2
148+
; RV32IZBA-NEXT: sb a1, 0(a0)
149+
; RV32IZBA-NEXT: ret
150+
;
151+
; RV32IZBAXQCISLS-LABEL: sb_ri:
152+
; RV32IZBAXQCISLS: # %bb.0:
153+
; RV32IZBAXQCISLS-NEXT: qc.srb a1, a0, a2, 7
154+
; RV32IZBAXQCISLS-NEXT: ret
155+
%shl = shl i32 %c, 7
156+
%1 = getelementptr i8, i8* %a, i32 %shl
157+
store i8 %b, i8* %1
158+
ret void
159+
}
160+
161+
define void @sh_ri(i16* %a, i16 %b, i32 %c) {
162+
; RV32I-LABEL: sh_ri:
163+
; RV32I: # %bb.0:
164+
; RV32I-NEXT: slli a2, a2, 3
165+
; RV32I-NEXT: add a0, a0, a2
166+
; RV32I-NEXT: sh a1, 0(a0)
167+
; RV32I-NEXT: ret
168+
;
169+
; RV32IZBA-LABEL: sh_ri:
170+
; RV32IZBA: # %bb.0:
171+
; RV32IZBA-NEXT: sh3add a0, a2, a0
172+
; RV32IZBA-NEXT: sh a1, 0(a0)
173+
; RV32IZBA-NEXT: ret
174+
;
175+
; RV32IZBAXQCISLS-LABEL: sh_ri:
176+
; RV32IZBAXQCISLS: # %bb.0:
177+
; RV32IZBAXQCISLS-NEXT: qc.srh a1, a0, a2, 3
178+
; RV32IZBAXQCISLS-NEXT: ret
179+
%shl = shl i32 %c, 2
180+
%1 = getelementptr i16, i16* %a, i32 %shl
181+
store i16 %b, i16* %1
182+
ret void
183+
}
184+
185+
define void @sw_ri(i32* %a, i32 %b, i32 %c) {
186+
; RV32I-LABEL: sw_ri:
187+
; RV32I: # %bb.0:
188+
; RV32I-NEXT: slli a2, a2, 3
189+
; RV32I-NEXT: add a0, a0, a2
190+
; RV32I-NEXT: sw a1, 0(a0)
191+
; RV32I-NEXT: ret
192+
;
193+
; RV32IZBA-LABEL: sw_ri:
194+
; RV32IZBA: # %bb.0:
195+
; RV32IZBA-NEXT: sh3add a0, a2, a0
196+
; RV32IZBA-NEXT: sw a1, 0(a0)
197+
; RV32IZBA-NEXT: ret
198+
;
199+
; RV32IZBAXQCISLS-LABEL: sw_ri:
200+
; RV32IZBAXQCISLS: # %bb.0:
201+
; RV32IZBAXQCISLS-NEXT: qc.srw a1, a0, a2, 3
202+
; RV32IZBAXQCISLS-NEXT: ret
203+
%shl = shl i32 %c, 1
204+
%1 = getelementptr i32, i32* %a, i32 %shl
205+
store i32 %b, i32* %1
206+
ret void
207+
}

0 commit comments

Comments
 (0)