Skip to content

Commit 283f53a

Browse files
authored
[RISCV] Add isel patterns for generating XAndesPerf branch immediate instructions (#145147)
Similar to #139872. This patch adds isel patterns to match `riscv_brcc` and `riscv_selectcc_frag` to XAndesPerf branch instructions.
1 parent 4cf53cd commit 283f53a

File tree

7 files changed

+1154
-334
lines changed

7 files changed

+1154
-334
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,11 +2417,16 @@ unsigned RISCVTargetLowering::getVectorTypeBreakdownForCallingConv(
24172417
// with 1/-1.
24182418
static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
24192419
ISD::CondCode &CC, SelectionDAG &DAG) {
2420+
const RISCVSubtarget &Subtarget =
2421+
DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
2422+
24202423
// If this is a single bit test that can't be handled by ANDI, shift the
24212424
// bit to be tested to the MSB and perform a signed compare with 0.
24222425
if (isIntEqualitySetCC(CC) && isNullConstant(RHS) &&
24232426
LHS.getOpcode() == ISD::AND && LHS.hasOneUse() &&
2424-
isa<ConstantSDNode>(LHS.getOperand(1))) {
2427+
isa<ConstantSDNode>(LHS.getOperand(1)) &&
2428+
// XAndesPerf supports branch on test bit.
2429+
!Subtarget.hasVendorXAndesPerf()) {
24252430
uint64_t Mask = LHS.getConstantOperandVal(1);
24262431
if ((isPowerOf2_64(Mask) || isMask_64(Mask)) && !isInt<12>(Mask)) {
24272432
unsigned ShAmt = 0;
@@ -2442,8 +2447,6 @@ static void translateSetCCForBranch(const SDLoc &DL, SDValue &LHS, SDValue &RHS,
24422447

24432448
if (auto *RHSC = dyn_cast<ConstantSDNode>(RHS)) {
24442449
int64_t C = RHSC->getSExtValue();
2445-
const RISCVSubtarget &Subtarget =
2446-
DAG.getMachineFunction().getSubtarget<RISCVSubtarget>();
24472450
switch (CC) {
24482451
default: break;
24492452
case ISD::SETGT:
@@ -18273,6 +18276,14 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
1827318276
uint64_t Mask = LHS0.getConstantOperandVal(1);
1827418277
uint64_t ShAmt = LHS.getConstantOperandVal(1);
1827518278
if (isPowerOf2_64(Mask) && Log2_64(Mask) == ShAmt) {
18279+
// XAndesPerf supports branch on test bit.
18280+
if (Subtarget.hasVendorXAndesPerf()) {
18281+
LHS =
18282+
DAG.getNode(ISD::AND, DL, LHS.getValueType(), LHS0.getOperand(0),
18283+
DAG.getConstant(Mask, DL, LHS.getValueType()));
18284+
return true;
18285+
}
18286+
1827618287
CCVal = CCVal == ISD::SETEQ ? ISD::SETGE : ISD::SETLT;
1827718288
CC = DAG.getCondCode(CCVal);
1827818289

@@ -21795,6 +21806,8 @@ RISCVTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
2179521806
case RISCV::Select_GPRNoX0_Using_CC_UImm5NonZero_QC:
2179621807
case RISCV::Select_GPRNoX0_Using_CC_SImm16NonZero_QC:
2179721808
case RISCV::Select_GPRNoX0_Using_CC_UImm16NonZero_QC:
21809+
case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
21810+
case RISCV::Select_GPR_Using_CC_UImm7_NDS:
2179821811
case RISCV::Select_FPR16_Using_CC_GPR:
2179921812
case RISCV::Select_FPR16INX_Using_CC_GPR:
2180021813
case RISCV::Select_FPR32_Using_CC_GPR:

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,11 +964,15 @@ RISCVCC::CondCode RISCVInstrInfo::getCondFromBranchOpc(unsigned Opc) {
964964
case RISCV::CV_BEQIMM:
965965
case RISCV::QC_BEQI:
966966
case RISCV::QC_E_BEQI:
967+
case RISCV::NDS_BBC:
968+
case RISCV::NDS_BEQC:
967969
return RISCVCC::COND_EQ;
968970
case RISCV::BNE:
969971
case RISCV::QC_BNEI:
970972
case RISCV::QC_E_BNEI:
971973
case RISCV::CV_BNEIMM:
974+
case RISCV::NDS_BBS:
975+
case RISCV::NDS_BNEC:
972976
return RISCVCC::COND_NE;
973977
case RISCV::BLT:
974978
case RISCV::QC_BLTI:
@@ -1101,6 +1105,26 @@ unsigned RISCVCC::getBrCond(RISCVCC::CondCode CC, unsigned SelectOpc) {
11011105
return RISCV::QC_E_BGEUI;
11021106
}
11031107
break;
1108+
case RISCV::Select_GPR_Using_CC_UImmLog2XLen_NDS:
1109+
switch (CC) {
1110+
default:
1111+
llvm_unreachable("Unexpected condition code!");
1112+
case RISCVCC::COND_EQ:
1113+
return RISCV::NDS_BBC;
1114+
case RISCVCC::COND_NE:
1115+
return RISCV::NDS_BBS;
1116+
}
1117+
break;
1118+
case RISCV::Select_GPR_Using_CC_UImm7_NDS:
1119+
switch (CC) {
1120+
default:
1121+
llvm_unreachable("Unexpected condition code!");
1122+
case RISCVCC::COND_EQ:
1123+
return RISCV::NDS_BEQC;
1124+
case RISCVCC::COND_NE:
1125+
return RISCV::NDS_BNEC;
1126+
}
1127+
break;
11041128
}
11051129
}
11061130

@@ -1398,6 +1422,18 @@ bool RISCVInstrInfo::reverseBranchCondition(
13981422
case RISCV::QC_E_BLTUI:
13991423
Cond[0].setImm(RISCV::QC_E_BGEUI);
14001424
break;
1425+
case RISCV::NDS_BBC:
1426+
Cond[0].setImm(RISCV::NDS_BBS);
1427+
break;
1428+
case RISCV::NDS_BBS:
1429+
Cond[0].setImm(RISCV::NDS_BBC);
1430+
break;
1431+
case RISCV::NDS_BEQC:
1432+
Cond[0].setImm(RISCV::NDS_BNEC);
1433+
break;
1434+
case RISCV::NDS_BNEC:
1435+
Cond[0].setImm(RISCV::NDS_BEQC);
1436+
break;
14011437
}
14021438

14031439
return false;
@@ -1570,6 +1606,11 @@ bool RISCVInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
15701606
switch (BranchOp) {
15711607
default:
15721608
llvm_unreachable("Unexpected opcode!");
1609+
case RISCV::NDS_BBC:
1610+
case RISCV::NDS_BBS:
1611+
case RISCV::NDS_BEQC:
1612+
case RISCV::NDS_BNEC:
1613+
return isInt<11>(BrOffset);
15731614
case RISCV::BEQ:
15741615
case RISCV::BNE:
15751616
case RISCV::BLT:

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ def uimm6 : RISCVUImmLeafOp<6>;
321321
def uimm7_opcode : RISCVUImmOp<7> {
322322
let ParserMatchClass = InsnDirectiveOpcode;
323323
}
324-
def uimm7 : RISCVUImmOp<7>;
324+
def uimm7 : RISCVUImmLeafOp<7>;
325325
def uimm8 : RISCVUImmOp<8>;
326326
def uimm16 : RISCVUImmOp<16>;
327327
def uimm32 : RISCVUImmOp<32>;

llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,17 @@ def simm20_lsb000 : Operand<XLenVT> {
5353
let DecoderMethod = "decodeSImmOperandAndLslN<20, 3>";
5454
}
5555

56+
// Predicate: True if immediate is a power of 2.
57+
def PowerOf2 : PatLeaf<(imm), [{
58+
return isPowerOf2_64(N->getZExtValue());
59+
}]>;
60+
61+
// Transformation function: Get log2 of immediate.
62+
def Log2 : SDNodeXForm<imm, [{
63+
uint64_t Imm = Log2_64(N->getZExtValue());
64+
return CurDAG->getTargetConstant(Imm, SDLoc(N), N->getValueType(0));
65+
}]>;
66+
5667
//===----------------------------------------------------------------------===//
5768
// Instruction Class Templates
5869
//===----------------------------------------------------------------------===//
@@ -556,8 +567,44 @@ def NDS_VD4DOTSU_VV : NDSRVInstVD4DOT<0b000101, "nds.vd4dotsu">;
556567
// Pseudo-instructions and codegen patterns
557568
//===----------------------------------------------------------------------===//
558569

570+
class NDS_BBPat<CondCode Cond, NDSRVInstBB Inst>
571+
: Pat<(riscv_brcc (and(XLenVT GPR:$rs1), PowerOf2:$mask), 0, Cond,
572+
bb:$imm10),
573+
(Inst GPR:$rs1, (Log2 PowerOf2:$mask), bare_simm11_lsb0:$imm10)>;
574+
575+
class NDS_BCPat<CondCode Cond, NDSRVInstBC Inst>
576+
: Pat<(riscv_brcc (XLenVT GPR:$rs1), uimm7:$cimm, Cond, bb:$imm10),
577+
(Inst GPR:$rs1, uimm7:$cimm, bare_simm11_lsb0:$imm10)>;
578+
579+
defm CC_UImmLog2XLen_NDS : SelectCC_GPR_riirr<GPR, uimmlog2xlen>;
580+
defm CC_UImm7_NDS : SelectCC_GPR_riirr<GPR, uimm7>;
581+
582+
class SelectNDS_BB<CondCode Cond>
583+
: Pat<(riscv_selectcc_frag:$cc (and(XLenVT GPR:$lhs), PowerOf2:$mask), 0,
584+
Cond, (XLenVT GPR:$truev), GPR:$falsev),
585+
(Select_GPR_Using_CC_UImmLog2XLen_NDS GPR:$lhs, (Log2 PowerOf2:$mask),
586+
(IntCCtoRISCVCC $cc), GPR:$truev, GPR:$falsev)>;
587+
588+
class SelectNDS_BC<CondCode Cond>
589+
: Pat<(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs), uimm7:$cimm, Cond,
590+
(XLenVT GPR:$truev), GPR:$falsev),
591+
(Select_GPR_Using_CC_UImm7_NDS GPR:$lhs, uimm7:$cimm,
592+
(IntCCtoRISCVCC $cc), GPR:$truev, GPR:$falsev)>;
593+
559594
let Predicates = [HasVendorXAndesPerf] in {
560595

596+
def : NDS_BBPat<SETEQ, NDS_BBC>;
597+
def : NDS_BBPat<SETNE, NDS_BBS>;
598+
599+
def : SelectNDS_BB<SETEQ>;
600+
def : SelectNDS_BB<SETNE>;
601+
602+
def : NDS_BCPat<SETEQ, NDS_BEQC>;
603+
def : NDS_BCPat<SETNE, NDS_BNEC>;
604+
605+
def : SelectNDS_BC<SETEQ>;
606+
def : SelectNDS_BC<SETNE>;
607+
561608
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i16), (NDS_BFOS GPR:$rs1, 15, 0)>;
562609
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i8), (NDS_BFOS GPR:$rs1, 7, 0)>;
563610
def : Pat<(sext_inreg (XLenVT GPR:$rs1), i1), (NDS_BFOS GPR:$rs1, 0, 0)>;

llvm/lib/Target/RISCV/RISCVInstrPredicates.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ def isSelectPseudo
5454
Select_GPRNoX0_Using_CC_UImm5NonZero_QC,
5555
Select_GPRNoX0_Using_CC_SImm16NonZero_QC,
5656
Select_GPRNoX0_Using_CC_UImm16NonZero_QC,
57+
Select_GPR_Using_CC_UImmLog2XLen_NDS,
58+
Select_GPR_Using_CC_UImm7_NDS,
5759
Select_FPR16_Using_CC_GPR,
5860
Select_FPR16INX_Using_CC_GPR,
5961
Select_FPR32_Using_CC_GPR,

llvm/test/CodeGen/RISCV/rv32xandesperf.ll

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,170 @@
22
; RUN: llc -O0 -mtriple=riscv32 -mattr=+xandesperf -verify-machineinstrs < %s \
33
; RUN: | FileCheck %s
44

5+
; NDS.BBC
6+
7+
define i32 @bbc(i32 %a) nounwind {
8+
; CHECK-LABEL: bbc:
9+
; CHECK: # %bb.0:
10+
; CHECK-NEXT: nds.bbc a0, 16, .LBB0_2
11+
; CHECK-NEXT: j .LBB0_1
12+
; CHECK-NEXT: .LBB0_1: # %f
13+
; CHECK-NEXT: li a0, 0
14+
; CHECK-NEXT: ret
15+
; CHECK-NEXT: .LBB0_2: # %t
16+
; CHECK-NEXT: li a0, 1
17+
; CHECK-NEXT: ret
18+
%and = and i32 %a, 65536
19+
%tst = icmp eq i32 %and, 0
20+
br i1 %tst, label %t, label %f
21+
f:
22+
ret i32 0
23+
t:
24+
ret i32 1
25+
}
26+
27+
define i32 @select_bbc(i32 %a, i32 %b, i32 %c) nounwind {
28+
; CHECK-LABEL: select_bbc:
29+
; CHECK: # %bb.0:
30+
; CHECK-NEXT: addi sp, sp, -16
31+
; CHECK-NEXT: sw a2, 8(sp) # 4-byte Folded Spill
32+
; CHECK-NEXT: sw a1, 12(sp) # 4-byte Folded Spill
33+
; CHECK-NEXT: nds.bbc a0, 16, .LBB1_2
34+
; CHECK-NEXT: # %bb.1:
35+
; CHECK-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
36+
; CHECK-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
37+
; CHECK-NEXT: .LBB1_2:
38+
; CHECK-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
39+
; CHECK-NEXT: addi sp, sp, 16
40+
; CHECK-NEXT: ret
41+
%and = and i32 %a, 65536
42+
%tst = icmp eq i32 %and, 0
43+
%ret = select i1 %tst, i32 %b, i32 %c
44+
ret i32 %ret
45+
}
46+
47+
; NDS.BBS
48+
49+
define i32 @bbs(i32 %a) nounwind {
50+
; CHECK-LABEL: bbs:
51+
; CHECK: # %bb.0:
52+
; CHECK-NEXT: nds.bbs a0, 16, .LBB2_2
53+
; CHECK-NEXT: j .LBB2_1
54+
; CHECK-NEXT: .LBB2_1: # %f
55+
; CHECK-NEXT: li a0, 0
56+
; CHECK-NEXT: ret
57+
; CHECK-NEXT: .LBB2_2: # %t
58+
; CHECK-NEXT: li a0, 1
59+
; CHECK-NEXT: ret
60+
%and = and i32 %a, 65536
61+
%tst = icmp ne i32 %and, 0
62+
br i1 %tst, label %t, label %f
63+
f:
64+
ret i32 0
65+
t:
66+
ret i32 1
67+
}
68+
69+
define i32 @select_bbs(i32 %a, i32 %b, i32 %c) nounwind {
70+
; CHECK-LABEL: select_bbs:
71+
; CHECK: # %bb.0:
72+
; CHECK-NEXT: addi sp, sp, -16
73+
; CHECK-NEXT: sw a2, 8(sp) # 4-byte Folded Spill
74+
; CHECK-NEXT: sw a1, 12(sp) # 4-byte Folded Spill
75+
; CHECK-NEXT: nds.bbs a0, 16, .LBB3_2
76+
; CHECK-NEXT: # %bb.1:
77+
; CHECK-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
78+
; CHECK-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
79+
; CHECK-NEXT: .LBB3_2:
80+
; CHECK-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
81+
; CHECK-NEXT: addi sp, sp, 16
82+
; CHECK-NEXT: ret
83+
%and = and i32 %a, 65536
84+
%tst = icmp ne i32 %and, 0
85+
%ret = select i1 %tst, i32 %b, i32 %c
86+
ret i32 %ret
87+
}
88+
89+
; NDS.BEQC
90+
91+
define i32 @beqc(i32 %a) nounwind {
92+
; CHECK-LABEL: beqc:
93+
; CHECK: # %bb.0:
94+
; CHECK-NEXT: nds.beqc a0, 5, .LBB4_2
95+
; CHECK-NEXT: j .LBB4_1
96+
; CHECK-NEXT: .LBB4_1: # %f
97+
; CHECK-NEXT: li a0, 0
98+
; CHECK-NEXT: ret
99+
; CHECK-NEXT: .LBB4_2: # %t
100+
; CHECK-NEXT: li a0, 1
101+
; CHECK-NEXT: ret
102+
%tst = icmp eq i32 %a, 5
103+
br i1 %tst, label %t, label %f
104+
f:
105+
ret i32 0
106+
t:
107+
ret i32 1
108+
}
109+
110+
define i32 @select_beqc(i32 %a, i32 %b, i32 %c) nounwind {
111+
; CHECK-LABEL: select_beqc:
112+
; CHECK: # %bb.0:
113+
; CHECK-NEXT: addi sp, sp, -16
114+
; CHECK-NEXT: sw a2, 8(sp) # 4-byte Folded Spill
115+
; CHECK-NEXT: sw a1, 12(sp) # 4-byte Folded Spill
116+
; CHECK-NEXT: nds.beqc a0, 5, .LBB5_2
117+
; CHECK-NEXT: # %bb.1:
118+
; CHECK-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
119+
; CHECK-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
120+
; CHECK-NEXT: .LBB5_2:
121+
; CHECK-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
122+
; CHECK-NEXT: addi sp, sp, 16
123+
; CHECK-NEXT: ret
124+
%tst = icmp eq i32 %a, 5
125+
%ret = select i1 %tst, i32 %b, i32 %c
126+
ret i32 %ret
127+
}
128+
129+
; NDS.BNEC
130+
131+
define i32 @bnec(i32 %a) nounwind {
132+
; CHECK-LABEL: bnec:
133+
; CHECK: # %bb.0:
134+
; CHECK-NEXT: nds.bnec a0, 5, .LBB6_2
135+
; CHECK-NEXT: j .LBB6_1
136+
; CHECK-NEXT: .LBB6_1: # %f
137+
; CHECK-NEXT: li a0, 0
138+
; CHECK-NEXT: ret
139+
; CHECK-NEXT: .LBB6_2: # %t
140+
; CHECK-NEXT: li a0, 1
141+
; CHECK-NEXT: ret
142+
%tst = icmp ne i32 %a, 5
143+
br i1 %tst, label %t, label %f
144+
f:
145+
ret i32 0
146+
t:
147+
ret i32 1
148+
}
149+
150+
define i32 @select_bnec(i32 %a, i32 %b, i32 %c) nounwind {
151+
; CHECK-LABEL: select_bnec:
152+
; CHECK: # %bb.0:
153+
; CHECK-NEXT: addi sp, sp, -16
154+
; CHECK-NEXT: sw a2, 8(sp) # 4-byte Folded Spill
155+
; CHECK-NEXT: sw a1, 12(sp) # 4-byte Folded Spill
156+
; CHECK-NEXT: nds.bnec a0, 5, .LBB7_2
157+
; CHECK-NEXT: # %bb.1:
158+
; CHECK-NEXT: lw a0, 8(sp) # 4-byte Folded Reload
159+
; CHECK-NEXT: sw a0, 12(sp) # 4-byte Folded Spill
160+
; CHECK-NEXT: .LBB7_2:
161+
; CHECK-NEXT: lw a0, 12(sp) # 4-byte Folded Reload
162+
; CHECK-NEXT: addi sp, sp, 16
163+
; CHECK-NEXT: ret
164+
%tst = icmp ne i32 %a, 5
165+
%ret = select i1 %tst, i32 %b, i32 %c
166+
ret i32 %ret
167+
}
168+
5169
; NDS.BFOZ
6170

7171
; MSB >= LSB

0 commit comments

Comments
 (0)