Skip to content

Commit 8f8853a

Browse files
authored
[RISCV] Add ISel patterns for Xqcia instructions (#136548)
This patch adds instruction selection patterns for generating the integer arithmetic instructions.
1 parent c1940cd commit 8f8853a

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,15 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
422422
else if (!Subtarget.hasVendorXTHeadCondMov())
423423
setOperationAction(ISD::SELECT, XLenVT, Custom);
424424

425+
if (Subtarget.hasVendorXqcia() && !Subtarget.is64Bit()) {
426+
setOperationAction(ISD::UADDSAT, MVT::i32, Legal);
427+
setOperationAction(ISD::SADDSAT, MVT::i32, Legal);
428+
setOperationAction(ISD::USUBSAT, MVT::i32, Legal);
429+
setOperationAction(ISD::SSUBSAT, MVT::i32, Legal);
430+
setOperationAction(ISD::SSHLSAT, MVT::i32, Legal);
431+
setOperationAction(ISD::USHLSAT, MVT::i32, Legal);
432+
}
433+
425434
static const unsigned FPLegalNodeTypes[] = {
426435
ISD::FMINNUM, ISD::FMAXNUM, ISD::FMINIMUMNUM,
427436
ISD::FMAXIMUMNUM, ISD::LRINT, ISD::LLRINT,

llvm/lib/Target/RISCV/RISCVInstrInfoXqci.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,6 +1247,10 @@ class PatGprNoX0Simm32NoSimm26<SDPatternOperator OpNode, RVInst48 Inst>
12471247
: Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), simm32_nosimm26:$imm)),
12481248
(Inst GPRNoX0:$rs1, simm32_nosimm26:$imm)>;
12491249

1250+
class PatGprNoX0GprNoX0<SDPatternOperator OpNode, RVInstR Inst>
1251+
: Pat<(i32 (OpNode (i32 GPRNoX0:$rs1), (i32 GPRNoX0:$rs2))),
1252+
(Inst GPRNoX0:$rs1, GPRNoX0:$rs2)>;
1253+
12501254
class QC48LdPat<PatFrag LoadOp, RVInst48 Inst>
12511255
: Pat<(i32 (LoadOp (AddLike (i32 GPR:$rs1), simm26_nosimm12:$imm26))),
12521256
(Inst GPR:$rs1, simm26_nosimm12:$imm26)>;
@@ -1308,5 +1312,14 @@ let Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1 in {
13081312
def : QCScaledStPat<store, QC_SRW>;
13091313
} // Predicates = [HasVendorXqcisls, IsRV32], AddedComplexity = 1
13101314

1315+
let Predicates = [HasVendorXqcia, IsRV32] in {
1316+
def : PatGprNoX0GprNoX0<saddsat, QC_ADDSAT>;
1317+
def : PatGprNoX0GprNoX0<uaddsat, QC_ADDUSAT>;
1318+
def : PatGprNoX0GprNoX0<ssubsat, QC_SUBSAT>;
1319+
def : PatGprNoX0GprNoX0<usubsat, QC_SUBUSAT>;
1320+
def : PatGprNoX0GprNoX0<ushlsat, QC_SHLUSAT>;
1321+
def : PatGprNoX0GprNoX0<sshlsat, QC_SHLSAT>;
1322+
} // Predicates = [HasVendorXqcia, IsRV32]
1323+
13111324
let Predicates = [HasVendorXqciint, IsRV32] in
13121325
def : Pat<(riscv_mileaveret_glue), (QC_C_MILEAVERET)>;

llvm/test/CodeGen/RISCV/xqcia.ll

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; Test that we are able to generate the Xqcia instructions
3+
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
4+
; RUN: | FileCheck %s --check-prefixes=RV32I
5+
; RUN: llc -mtriple=riscv32 -mattr=+experimental-xqcia -verify-machineinstrs < %s \
6+
; RUN: | FileCheck %s --check-prefixes=RV32IXQCIA
7+
8+
define i32 @addsat(i32 %a, i32 %b) {
9+
; RV32I-LABEL: addsat:
10+
; RV32I: # %bb.0:
11+
; RV32I-NEXT: mv a2, a0
12+
; RV32I-NEXT: add a0, a0, a1
13+
; RV32I-NEXT: slt a2, a0, a2
14+
; RV32I-NEXT: slti a1, a1, 0
15+
; RV32I-NEXT: beq a1, a2, .LBB0_2
16+
; RV32I-NEXT: # %bb.1:
17+
; RV32I-NEXT: srai a0, a0, 31
18+
; RV32I-NEXT: lui a1, 524288
19+
; RV32I-NEXT: xor a0, a0, a1
20+
; RV32I-NEXT: .LBB0_2:
21+
; RV32I-NEXT: ret
22+
;
23+
; RV32IXQCIA-LABEL: addsat:
24+
; RV32IXQCIA: # %bb.0:
25+
; RV32IXQCIA-NEXT: qc.addsat a0, a0, a1
26+
; RV32IXQCIA-NEXT: ret
27+
%saddsat = tail call i32 @llvm.sadd.sat.i32(i32 %a,i32 %b)
28+
ret i32 %saddsat
29+
}
30+
31+
define i32 @addusat(i32 %a, i32 %b) {
32+
; RV32I-LABEL: addusat:
33+
; RV32I: # %bb.0:
34+
; RV32I-NEXT: add a1, a0, a1
35+
; RV32I-NEXT: sltu a0, a1, a0
36+
; RV32I-NEXT: neg a0, a0
37+
; RV32I-NEXT: or a0, a0, a1
38+
; RV32I-NEXT: ret
39+
;
40+
; RV32IXQCIA-LABEL: addusat:
41+
; RV32IXQCIA: # %bb.0:
42+
; RV32IXQCIA-NEXT: qc.addusat a0, a0, a1
43+
; RV32IXQCIA-NEXT: ret
44+
%uaddsat = tail call i32 @llvm.uadd.sat.i32(i32 %a,i32 %b)
45+
ret i32 %uaddsat
46+
}
47+
48+
define i32 @subsat(i32 %a, i32 %b) {
49+
; RV32I-LABEL: subsat:
50+
; RV32I: # %bb.0:
51+
; RV32I-NEXT: mv a2, a0
52+
; RV32I-NEXT: sgtz a3, a1
53+
; RV32I-NEXT: sub a0, a0, a1
54+
; RV32I-NEXT: slt a1, a0, a2
55+
; RV32I-NEXT: beq a3, a1, .LBB2_2
56+
; RV32I-NEXT: # %bb.1:
57+
; RV32I-NEXT: srai a0, a0, 31
58+
; RV32I-NEXT: lui a1, 524288
59+
; RV32I-NEXT: xor a0, a0, a1
60+
; RV32I-NEXT: .LBB2_2:
61+
; RV32I-NEXT: ret
62+
;
63+
; RV32IXQCIA-LABEL: subsat:
64+
; RV32IXQCIA: # %bb.0:
65+
; RV32IXQCIA-NEXT: qc.subsat a0, a0, a1
66+
; RV32IXQCIA-NEXT: ret
67+
%ssubsat = tail call i32 @llvm.ssub.sat.i32(i32 %a,i32 %b)
68+
ret i32 %ssubsat
69+
}
70+
71+
define i32 @subusat(i32 %a, i32 %b) {
72+
; RV32I-LABEL: subusat:
73+
; RV32I: # %bb.0:
74+
; RV32I-NEXT: sub a1, a0, a1
75+
; RV32I-NEXT: sltu a0, a0, a1
76+
; RV32I-NEXT: addi a0, a0, -1
77+
; RV32I-NEXT: and a0, a0, a1
78+
; RV32I-NEXT: ret
79+
;
80+
; RV32IXQCIA-LABEL: subusat:
81+
; RV32IXQCIA: # %bb.0:
82+
; RV32IXQCIA-NEXT: qc.subusat a0, a0, a1
83+
; RV32IXQCIA-NEXT: ret
84+
%usubsat = tail call i32 @llvm.usub.sat.i32(i32 %a,i32 %b)
85+
ret i32 %usubsat
86+
}
87+
88+
define i32 @shlusat(i32 %a, i32 %b) {
89+
; RV32I-LABEL: shlusat:
90+
; RV32I: # %bb.0:
91+
; RV32I-NEXT: sll a2, a0, a1
92+
; RV32I-NEXT: srl a1, a2, a1
93+
; RV32I-NEXT: xor a0, a0, a1
94+
; RV32I-NEXT: seqz a0, a0
95+
; RV32I-NEXT: addi a0, a0, -1
96+
; RV32I-NEXT: or a0, a0, a2
97+
; RV32I-NEXT: ret
98+
;
99+
; RV32IXQCIA-LABEL: shlusat:
100+
; RV32IXQCIA: # %bb.0:
101+
; RV32IXQCIA-NEXT: qc.shlusat a0, a0, a1
102+
; RV32IXQCIA-NEXT: ret
103+
%ushlsat = tail call i32 @llvm.ushl.sat.i32(i32 %a,i32 %b)
104+
ret i32 %ushlsat
105+
}
106+
107+
define i32 @shlsat(i32 %a, i32 %b) {
108+
; RV32I-LABEL: shlsat:
109+
; RV32I: # %bb.0:
110+
; RV32I-NEXT: mv a2, a0
111+
; RV32I-NEXT: sll a0, a0, a1
112+
; RV32I-NEXT: sra a1, a0, a1
113+
; RV32I-NEXT: beq a2, a1, .LBB5_2
114+
; RV32I-NEXT: # %bb.1:
115+
; RV32I-NEXT: srai a2, a2, 31
116+
; RV32I-NEXT: lui a0, 524288
117+
; RV32I-NEXT: addi a0, a0, -1
118+
; RV32I-NEXT: xor a0, a2, a0
119+
; RV32I-NEXT: .LBB5_2:
120+
; RV32I-NEXT: ret
121+
;
122+
; RV32IXQCIA-LABEL: shlsat:
123+
; RV32IXQCIA: # %bb.0:
124+
; RV32IXQCIA-NEXT: qc.shlsat a0, a0, a1
125+
; RV32IXQCIA-NEXT: ret
126+
%sshlsat = tail call i32 @llvm.sshl.sat.i32(i32 %a,i32 %b)
127+
ret i32 %sshlsat
128+
}

0 commit comments

Comments
 (0)