Skip to content

Commit 9de657a

Browse files
authored
[RISCV] Add ISel patterns for Xqciac QC.MULIADD instruction (#147661)
Add basic isel patterns for the multiple accumulate QC.MULIADD instruction. While most case work with just the TD file pattern, there are few cases which need to be handled in ISelLowering depending on the immediate we are multiplying with: - imm + 1 , imm - 1, 1 - imm, -1 - imm are a power of 2 --> these become slli and add/sub - immediate is 2^n - 2 ^m --> this becomes (add/sub (shl X, C1), (shl X, C2)) - imm - 2, imm - 4, imm - 6 is a power of 2 --> these use shxadd when zba is enabled The patch does not decompose mul if Xqciac is present, for the above conditions. There could be cases where this may not beneficial which I plan to address in follow up patches.
1 parent a516c60 commit 9de657a

File tree

3 files changed

+284
-0
lines changed

3 files changed

+284
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15993,6 +15993,10 @@ static SDValue expandMul(SDNode *N, SelectionDAG &DAG,
1599315993
return SDValue();
1599415994
uint64_t MulAmt = CNode->getZExtValue();
1599515995

15996+
// Don't do this if the Xqciac extension is enabled and the MulAmt in simm12.
15997+
if (Subtarget.hasVendorXqciac() && isInt<12>(MulAmt))
15998+
return SDValue();
15999+
1599616000
const bool HasShlAdd = Subtarget.hasStdExtZba() ||
1599716001
Subtarget.hasVendorXTHeadBa() ||
1599816002
Subtarget.hasVendorXAndesPerf();
@@ -23752,6 +23756,10 @@ bool RISCVTargetLowering::decomposeMulByConstant(LLVMContext &Context, EVT VT,
2375223756
auto *ConstNode = cast<ConstantSDNode>(C);
2375323757
const APInt &Imm = ConstNode->getAPIntValue();
2375423758

23759+
// Don't do this if the Xqciac extension is enabled and the Imm in simm12.
23760+
if (Subtarget.hasVendorXqciac() && Imm.isSignedIntN(12))
23761+
return false;
23762+
2375523763
// Break the MUL to a SLLI and an ADD/SUB.
2375623764
if ((Imm + 1).isPowerOf2() || (Imm - 1).isPowerOf2() ||
2375723765
(1 - Imm).isPowerOf2() || (-1 - Imm).isPowerOf2())

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,6 +1356,11 @@ class SelectQCbi<CondCode Cond, DAGOperand InTyImm, Pseudo OpNode >
13561356
(OpNode GPRNoX0:$lhs, InTyImm:$Constant,
13571357
(IntCCtoRISCVCC $cc), GPRNoX0:$truev, GPRNoX0:$falsev)>;
13581358

1359+
let Predicates = [HasVendorXqciac, IsRV32] in {
1360+
def : Pat<(XLenVT (add GPRNoX0:$rd, (mul GPRNoX0:$rs1, simm12:$imm12))),
1361+
(QC_MULIADD GPRNoX0:$rd, GPRNoX0:$rs1, simm12:$imm12)>;
1362+
} // Predicates = [HasVendorXqciac, IsRV32]
1363+
13591364
/// Simple arithmetic operations
13601365

13611366
let Predicates = [HasVendorXqcilia, IsRV32] in {

llvm/test/CodeGen/RISCV/xqciac.ll

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc -mtriple=riscv32 -mattr=+m -verify-machineinstrs < %s \
3+
; RUN: | FileCheck %s -check-prefix=RV32IM
4+
; RUN: llc -mtriple=riscv32 -mattr=+m,+experimental-xqciac -verify-machineinstrs < %s \
5+
; RUN: | FileCheck %s -check-prefix=RV32IMXQCIAC
6+
; RUN: llc -mtriple=riscv32 -mattr=+m,+experimental-xqciac,+zba -verify-machineinstrs < %s \
7+
; RUN: | FileCheck %s -check-prefix=RV32IZBAMXQCIAC
8+
9+
define dso_local i32 @mul(i32 %a, i32 %b) local_unnamed_addr #0 {
10+
; RV32IM-LABEL: mul:
11+
; RV32IM: # %bb.0: # %entry
12+
; RV32IM-NEXT: slli a0, a1, 5
13+
; RV32IM-NEXT: add a0, a0, a1
14+
; RV32IM-NEXT: ret
15+
;
16+
; RV32IMXQCIAC-LABEL: mul:
17+
; RV32IMXQCIAC: # %bb.0: # %entry
18+
; RV32IMXQCIAC-NEXT: li a0, 33
19+
; RV32IMXQCIAC-NEXT: mul a0, a1, a0
20+
; RV32IMXQCIAC-NEXT: ret
21+
;
22+
; RV32IZBAMXQCIAC-LABEL: mul:
23+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
24+
; RV32IZBAMXQCIAC-NEXT: li a0, 33
25+
; RV32IZBAMXQCIAC-NEXT: mul a0, a1, a0
26+
; RV32IZBAMXQCIAC-NEXT: ret
27+
entry:
28+
%mul = mul nsw i32 %b, 33
29+
ret i32 %mul
30+
}
31+
32+
define dso_local i32 @muliadd(i32 %a, i32 %b) local_unnamed_addr #0 {
33+
; RV32IM-LABEL: muliadd:
34+
; RV32IM: # %bb.0: # %entry
35+
; RV32IM-NEXT: li a2, 165
36+
; RV32IM-NEXT: mul a1, a1, a2
37+
; RV32IM-NEXT: add a0, a1, a0
38+
; RV32IM-NEXT: ret
39+
;
40+
; RV32IMXQCIAC-LABEL: muliadd:
41+
; RV32IMXQCIAC: # %bb.0: # %entry
42+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 165
43+
; RV32IMXQCIAC-NEXT: ret
44+
;
45+
; RV32IZBAMXQCIAC-LABEL: muliadd:
46+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
47+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 165
48+
; RV32IZBAMXQCIAC-NEXT: ret
49+
entry:
50+
%mul = mul nsw i32 %b, 165
51+
%add = add nsw i32 %mul, %a
52+
ret i32 %add
53+
}
54+
55+
define dso_local i32 @muliadd2(i32 %a, i32 %b) local_unnamed_addr #0 {
56+
; RV32IM-LABEL: muliadd2:
57+
; RV32IM: # %bb.0: # %entry
58+
; RV32IM-NEXT: li a2, 1111
59+
; RV32IM-NEXT: mul a1, a1, a2
60+
; RV32IM-NEXT: add a0, a1, a0
61+
; RV32IM-NEXT: ret
62+
;
63+
; RV32IMXQCIAC-LABEL: muliadd2:
64+
; RV32IMXQCIAC: # %bb.0: # %entry
65+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 1111
66+
; RV32IMXQCIAC-NEXT: ret
67+
;
68+
; RV32IZBAMXQCIAC-LABEL: muliadd2:
69+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
70+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 1111
71+
; RV32IZBAMXQCIAC-NEXT: ret
72+
entry:
73+
%mul = mul nsw i32 %b, 1111
74+
%add = add nsw i32 %mul, %a
75+
ret i32 %add
76+
}
77+
78+
define dso_local i32 @muliadd_neg(i32 %a, i32 %b) local_unnamed_addr #0 {
79+
; RV32IM-LABEL: muliadd_neg:
80+
; RV32IM: # %bb.0: # %entry
81+
; RV32IM-NEXT: li a2, -165
82+
; RV32IM-NEXT: mul a1, a1, a2
83+
; RV32IM-NEXT: add a0, a1, a0
84+
; RV32IM-NEXT: ret
85+
;
86+
; RV32IMXQCIAC-LABEL: muliadd_neg:
87+
; RV32IMXQCIAC: # %bb.0: # %entry
88+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, -165
89+
; RV32IMXQCIAC-NEXT: ret
90+
;
91+
; RV32IZBAMXQCIAC-LABEL: muliadd_neg:
92+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
93+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, -165
94+
; RV32IZBAMXQCIAC-NEXT: ret
95+
entry:
96+
%mul = mul nsw i32 %b, -165
97+
%add = add nsw i32 %mul, %a
98+
ret i32 %add
99+
}
100+
101+
define dso_local i32 @muliadd_neg2(i32 %a, i32 %b) local_unnamed_addr #0 {
102+
; RV32IM-LABEL: muliadd_neg2:
103+
; RV32IM: # %bb.0: # %entry
104+
; RV32IM-NEXT: li a2, -2045
105+
; RV32IM-NEXT: mul a1, a1, a2
106+
; RV32IM-NEXT: add a0, a1, a0
107+
; RV32IM-NEXT: ret
108+
;
109+
; RV32IMXQCIAC-LABEL: muliadd_neg2:
110+
; RV32IMXQCIAC: # %bb.0: # %entry
111+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, -2045
112+
; RV32IMXQCIAC-NEXT: ret
113+
;
114+
; RV32IZBAMXQCIAC-LABEL: muliadd_neg2:
115+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
116+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, -2045
117+
; RV32IZBAMXQCIAC-NEXT: ret
118+
entry:
119+
%mul = mul nsw i32 %b, -2045
120+
%add = add nsw i32 %mul, %a
121+
ret i32 %add
122+
}
123+
124+
define dso_local i32 @pow2immplus1(i32 %a, i32 %b) local_unnamed_addr #0 {
125+
; RV32IM-LABEL: pow2immplus1:
126+
; RV32IM: # %bb.0: # %entry
127+
; RV32IM-NEXT: slli a2, a1, 5
128+
; RV32IM-NEXT: add a0, a1, a0
129+
; RV32IM-NEXT: add a0, a2, a0
130+
; RV32IM-NEXT: ret
131+
;
132+
; RV32IMXQCIAC-LABEL: pow2immplus1:
133+
; RV32IMXQCIAC: # %bb.0: # %entry
134+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 33
135+
; RV32IMXQCIAC-NEXT: ret
136+
;
137+
; RV32IZBAMXQCIAC-LABEL: pow2immplus1:
138+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
139+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 33
140+
; RV32IZBAMXQCIAC-NEXT: ret
141+
entry:
142+
%mul = mul nsw i32 %b, 33
143+
%add = add nsw i32 %mul, %a
144+
ret i32 %add
145+
}
146+
147+
define dso_local i32 @pow2immminus2(i32 %a, i32 %b) local_unnamed_addr #0 {
148+
; RV32IM-LABEL: pow2immminus2:
149+
; RV32IM: # %bb.0: # %entry
150+
; RV32IM-NEXT: slli a2, a1, 1
151+
; RV32IM-NEXT: slli a1, a1, 7
152+
; RV32IM-NEXT: sub a1, a1, a2
153+
; RV32IM-NEXT: add a0, a1, a0
154+
; RV32IM-NEXT: ret
155+
;
156+
; RV32IMXQCIAC-LABEL: pow2immminus2:
157+
; RV32IMXQCIAC: # %bb.0: # %entry
158+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 126
159+
; RV32IMXQCIAC-NEXT: ret
160+
;
161+
; RV32IZBAMXQCIAC-LABEL: pow2immminus2:
162+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
163+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 126
164+
; RV32IZBAMXQCIAC-NEXT: ret
165+
entry:
166+
%mul = mul nsw i32 %b, 126
167+
%add = add nsw i32 %mul, %a
168+
ret i32 %add
169+
}
170+
171+
define dso_local i32 @pow2minuspow2(i32 %a, i32 %b) local_unnamed_addr #0 {
172+
; RV32IM-LABEL: pow2minuspow2:
173+
; RV32IM: # %bb.0: # %entry
174+
; RV32IM-NEXT: slli a2, a1, 7
175+
; RV32IM-NEXT: slli a1, a1, 9
176+
; RV32IM-NEXT: sub a1, a1, a2
177+
; RV32IM-NEXT: add a0, a1, a0
178+
; RV32IM-NEXT: ret
179+
;
180+
; RV32IMXQCIAC-LABEL: pow2minuspow2:
181+
; RV32IMXQCIAC: # %bb.0: # %entry
182+
; RV32IMXQCIAC-NEXT: qc.muliadd a0, a1, 384
183+
; RV32IMXQCIAC-NEXT: ret
184+
;
185+
; RV32IZBAMXQCIAC-LABEL: pow2minuspow2:
186+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
187+
; RV32IZBAMXQCIAC-NEXT: qc.muliadd a0, a1, 384
188+
; RV32IZBAMXQCIAC-NEXT: ret
189+
entry:
190+
%mul = mul nsw i32 %b, 384
191+
%add = add nsw i32 %mul, %a
192+
ret i32 %add
193+
}
194+
195+
define dso_local i32 @gtsimm12(i32 %a, i32 %b) local_unnamed_addr #0 {
196+
; RV32IM-LABEL: gtsimm12:
197+
; RV32IM: # %bb.0: # %entry
198+
; RV32IM-NEXT: lui a2, 1
199+
; RV32IM-NEXT: addi a2, a2, 477
200+
; RV32IM-NEXT: mul a1, a1, a2
201+
; RV32IM-NEXT: add a0, a1, a0
202+
; RV32IM-NEXT: ret
203+
;
204+
; RV32IMXQCIAC-LABEL: gtsimm12:
205+
; RV32IMXQCIAC: # %bb.0: # %entry
206+
; RV32IMXQCIAC-NEXT: lui a2, 1
207+
; RV32IMXQCIAC-NEXT: addi a2, a2, 477
208+
; RV32IMXQCIAC-NEXT: mul a1, a1, a2
209+
; RV32IMXQCIAC-NEXT: add a0, a0, a1
210+
; RV32IMXQCIAC-NEXT: ret
211+
;
212+
; RV32IZBAMXQCIAC-LABEL: gtsimm12:
213+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
214+
; RV32IZBAMXQCIAC-NEXT: lui a2, 1
215+
; RV32IZBAMXQCIAC-NEXT: addi a2, a2, 477
216+
; RV32IZBAMXQCIAC-NEXT: mul a1, a1, a2
217+
; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
218+
; RV32IZBAMXQCIAC-NEXT: ret
219+
entry:
220+
%mul = mul nsw i32 %b, 4573
221+
%add = add nsw i32 %mul, %a
222+
ret i32 %add
223+
}
224+
225+
; NOTE: This will become qc.shladd once support is added
226+
define dso_local i32 @pow2(i32 %a, i32 %b) local_unnamed_addr #0 {
227+
; RV32IM-LABEL: pow2:
228+
; RV32IM: # %bb.0: # %entry
229+
; RV32IM-NEXT: slli a1, a1, 5
230+
; RV32IM-NEXT: add a0, a1, a0
231+
; RV32IM-NEXT: ret
232+
;
233+
; RV32IMXQCIAC-LABEL: pow2:
234+
; RV32IMXQCIAC: # %bb.0: # %entry
235+
; RV32IMXQCIAC-NEXT: slli a1, a1, 5
236+
; RV32IMXQCIAC-NEXT: add a0, a0, a1
237+
; RV32IMXQCIAC-NEXT: ret
238+
;
239+
; RV32IZBAMXQCIAC-LABEL: pow2:
240+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
241+
; RV32IZBAMXQCIAC-NEXT: slli a1, a1, 5
242+
; RV32IZBAMXQCIAC-NEXT: add a0, a0, a1
243+
; RV32IZBAMXQCIAC-NEXT: ret
244+
entry:
245+
%mul = mul nsw i32 %b, 32
246+
%add = add nsw i32 %mul, %a
247+
ret i32 %add
248+
}
249+
250+
define dso_local i32 @shxadd(i32 %a, i32 %b) local_unnamed_addr #0 {
251+
; RV32IM-LABEL: shxadd:
252+
; RV32IM: # %bb.0: # %entry
253+
; RV32IM-NEXT: slli a1, a1, 1
254+
; RV32IM-NEXT: add a0, a1, a0
255+
; RV32IM-NEXT: ret
256+
;
257+
; RV32IMXQCIAC-LABEL: shxadd:
258+
; RV32IMXQCIAC: # %bb.0: # %entry
259+
; RV32IMXQCIAC-NEXT: slli a1, a1, 1
260+
; RV32IMXQCIAC-NEXT: add a0, a0, a1
261+
; RV32IMXQCIAC-NEXT: ret
262+
;
263+
; RV32IZBAMXQCIAC-LABEL: shxadd:
264+
; RV32IZBAMXQCIAC: # %bb.0: # %entry
265+
; RV32IZBAMXQCIAC-NEXT: sh1add a0, a1, a0
266+
; RV32IZBAMXQCIAC-NEXT: ret
267+
entry:
268+
%mul = mul nsw i32 %b, 2
269+
%add = add nsw i32 %mul, %a
270+
ret i32 %add
271+
}

0 commit comments

Comments
 (0)