Skip to content

Commit eab3a4a

Browse files
tclin914rorth
authored andcommitted
[RISCV] Select unsigned bitfield insert for XAndesPerf (llvm#142737)
The XAndesPerf extension includes unsigned bitfield extraction instruction `NDS.BFOZ`, which can extract the bits from 0 to Len -1, place them starting at bit Msb, and zero-fills the remaining bits. This patch handles the cases where Msb < Lsb for `NDS.BFOZ`. Instruction Sytax: nds.bfoz Rd, Rs1, Msb, Lsb The operation is: if Msb < Lsb: Lenm1 = Lsb - Msb; Rd[Lsb:Msb] = Rs1[Lenm1:0]; if (Lsb < (XLen -1)) Rd[XLen-1:Lsb+1]=0; Rd[Msb-1:0]=0; When Len == 1, it is a special case where the Msb is set to 0 instead of being equal to the Lsb.
1 parent 3858b53 commit eab3a4a

File tree

5 files changed

+180
-2
lines changed

5 files changed

+180
-2
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,26 @@ bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL,
688688
return true;
689689
}
690690

691+
bool RISCVDAGToDAGISel::tryUnsignedBitfieldInsertInZero(SDNode *Node, SDLoc DL,
692+
MVT VT, SDValue X,
693+
unsigned Msb,
694+
unsigned Lsb) {
695+
// Only supported with XAndesPerf at the moment.
696+
if (!Subtarget->hasVendorXAndesPerf())
697+
return false;
698+
699+
unsigned Opc = RISCV::NDS_BFOZ;
700+
701+
// If the Lsb is equal to the Msb, then the Lsb should be 0.
702+
if (Lsb == Msb)
703+
Lsb = 0;
704+
SDNode *Ubi = CurDAG->getMachineNode(Opc, DL, VT, X,
705+
CurDAG->getTargetConstant(Lsb, DL, VT),
706+
CurDAG->getTargetConstant(Msb, DL, VT));
707+
ReplaceNode(Node, Ubi);
708+
return true;
709+
}
710+
691711
bool RISCVDAGToDAGISel::tryIndexedLoad(SDNode *Node) {
692712
// Target does not support indexed loads.
693713
if (!Subtarget->hasVendorXTHeadMemIdx())
@@ -1324,6 +1344,19 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
13241344
return;
13251345
}
13261346

1347+
// Try to use an unsigned bitfield insert (e.g., nds.bfoz) if
1348+
// available.
1349+
// Transform (and (shl x, c2), c1)
1350+
// -> (<bfinsert> x, msb, lsb)
1351+
// e.g.
1352+
// (and (shl x, 12), 0x00fff000)
1353+
// If XLen = 32 and C2 = 12, then
1354+
// Msb = 32 - 8 - 1 = 23 and Lsb = 12
1355+
const unsigned Msb = XLen - Leading - 1;
1356+
const unsigned Lsb = C2;
1357+
if (tryUnsignedBitfieldInsertInZero(Node, DL, VT, X, Msb, Lsb))
1358+
return;
1359+
13271360
// (srli (slli c2+c3), c3)
13281361
if (OneUseOrZExtW && !IsCANDI) {
13291362
SDNode *SLLI = CurDAG->getMachineNode(

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
7979
bool trySignedBitfieldExtract(SDNode *Node);
8080
bool tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL, MVT VT, SDValue X,
8181
unsigned Msb, unsigned Lsb);
82+
bool tryUnsignedBitfieldInsertInZero(SDNode *Node, SDLoc DL, MVT VT,
83+
SDValue X, unsigned Msb, unsigned Lsb);
8284
bool tryIndexedLoad(SDNode *Node);
8385

8486
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);

llvm/test/CodeGen/RISCV/rv32xandesperf.ll

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

5+
; NDS.BFOZ
6+
7+
; MSB >= LSB
8+
59
define i32 @bfoz_from_and_i32(i32 %x) {
610
; CHECK-LABEL: bfoz_from_and_i32:
711
; CHECK: # %bb.0:
@@ -70,6 +74,54 @@ define i64 @bfoz_from_lshr_and_i64(i64 %x) {
7074
ret i64 %shifted
7175
}
7276

77+
; MSB = 0
78+
79+
define i32 @bfoz_from_and_shl_with_msb_zero_i32(i32 %x) {
80+
; CHECK-LABEL: bfoz_from_and_shl_with_msb_zero_i32:
81+
; CHECK: # %bb.0:
82+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 15
83+
; CHECK-NEXT: ret
84+
%shifted = shl i32 %x, 15
85+
%masked = and i32 %shifted, 32768
86+
ret i32 %masked
87+
}
88+
89+
define i32 @bfoz_from_lshr_shl_with_msb_zero_i32(i32 %x) {
90+
; CHECK-LABEL: bfoz_from_lshr_shl_with_msb_zero_i32:
91+
; CHECK: # %bb.0:
92+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 18
93+
; CHECK-NEXT: ret
94+
%shl = shl i32 %x, 31
95+
%lshr = lshr i32 %shl, 13
96+
ret i32 %lshr
97+
}
98+
99+
; MSB < LSB
100+
101+
define i32 @bfoz_from_and_shl_i32(i32 %x) {
102+
; CHECK-LABEL: bfoz_from_and_shl_i32:
103+
; CHECK: # %bb.0:
104+
; CHECK-NEXT: nds.bfoz a0, a0, 12, 23
105+
; CHECK-NEXT: ret
106+
%shifted = shl i32 %x, 12
107+
%masked = and i32 %shifted, 16773120
108+
ret i32 %masked
109+
}
110+
111+
define i32 @bfoz_from_lshr_shl_i32(i32 %x) {
112+
; CHECK-LABEL: bfoz_from_lshr_shl_i32:
113+
; CHECK: # %bb.0:
114+
; CHECK-NEXT: nds.bfoz a0, a0, 19, 24
115+
; CHECK-NEXT: ret
116+
%shl = shl i32 %x, 26
117+
%lshr = lshr i32 %shl, 7
118+
ret i32 %lshr
119+
}
120+
121+
; NDS.BFOS
122+
123+
; MSB >= LSB
124+
73125
define i32 @bfos_from_ashr_shl_i32(i32 %x) {
74126
; CHECK-LABEL: bfos_from_ashr_shl_i32:
75127
; CHECK: # %bb.0:

llvm/test/CodeGen/RISCV/rv64xandesperf.ll

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

5+
; NDS.BFOZ
6+
7+
; MSB >= LSB
8+
59
define i32 @bfoz_from_and_i32(i32 %x) {
610
; CHECK-LABEL: bfoz_from_and_i32:
711
; CHECK: # %bb.0:
@@ -60,6 +64,94 @@ define i64 @bfoz_from_lshr_and_i64(i64 %x) {
6064
ret i64 %shifted
6165
}
6266

67+
; MSB = 0
68+
69+
define i32 @bfoz_from_and_shl_with_msb_zero_i32(i32 %x) {
70+
; CHECK-LABEL: bfoz_from_and_shl_with_msb_zero_i32:
71+
; CHECK: # %bb.0:
72+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 15
73+
; CHECK-NEXT: ret
74+
%shifted = shl i32 %x, 15
75+
%masked = and i32 %shifted, 32768
76+
ret i32 %masked
77+
}
78+
79+
define i64 @bfoz_from_and_shl_with_msb_zero_i64(i64 %x) {
80+
; CHECK-LABEL: bfoz_from_and_shl_with_msb_zero_i64:
81+
; CHECK: # %bb.0:
82+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 48
83+
; CHECK-NEXT: ret
84+
%shifted = shl i64 %x, 48
85+
%masked = and i64 %shifted, 281474976710656
86+
ret i64 %masked
87+
}
88+
89+
define i32 @bfoz_from_lshr_shl_with_msb_zero_i32(i32 %x) {
90+
; CHECK-LABEL: bfoz_from_lshr_shl_with_msb_zero_i32:
91+
; CHECK: # %bb.0:
92+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 18
93+
; CHECK-NEXT: ret
94+
%shl = shl i32 %x, 31
95+
%lshr = lshr i32 %shl, 13
96+
ret i32 %lshr
97+
}
98+
99+
define i64 @bfoz_from_lshr_shl_with_msb_zero_i64(i64 %x) {
100+
; CHECK-LABEL: bfoz_from_lshr_shl_with_msb_zero_i64:
101+
; CHECK: # %bb.0:
102+
; CHECK-NEXT: nds.bfoz a0, a0, 0, 44
103+
; CHECK-NEXT: ret
104+
%shl = shl i64 %x, 63
105+
%lshr = lshr i64 %shl, 19
106+
ret i64 %lshr
107+
}
108+
109+
; MSB < LSB
110+
111+
define i32 @bfoz_from_and_shl_i32(i32 %x) {
112+
; CHECK-LABEL: bfoz_from_and_shl_i32:
113+
; CHECK: # %bb.0:
114+
; CHECK-NEXT: nds.bfoz a0, a0, 12, 23
115+
; CHECK-NEXT: ret
116+
%shifted = shl i32 %x, 12
117+
%masked = and i32 %shifted, 16773120
118+
ret i32 %masked
119+
}
120+
121+
define i64 @bfoz_from_and_shl_i64(i64 %x) {
122+
; CHECK-LABEL: bfoz_from_and_shl_i64:
123+
; CHECK: # %bb.0:
124+
; CHECK-NEXT: nds.bfoz a0, a0, 24, 35
125+
; CHECK-NEXT: ret
126+
%shifted = shl i64 %x, 24
127+
%masked = and i64 %shifted, 68702699520
128+
ret i64 %masked
129+
}
130+
131+
define i32 @bfoz_from_lshr_shl_i32(i32 %x) {
132+
; CHECK-LABEL: bfoz_from_lshr_shl_i32:
133+
; CHECK: # %bb.0:
134+
; CHECK-NEXT: nds.bfoz a0, a0, 19, 24
135+
; CHECK-NEXT: ret
136+
%shl = shl i32 %x, 26
137+
%lshr = lshr i32 %shl, 7
138+
ret i32 %lshr
139+
}
140+
141+
define i64 @bfoz_from_lshr_shl_i64(i64 %x) {
142+
; CHECK-LABEL: bfoz_from_lshr_shl_i64:
143+
; CHECK: # %bb.0:
144+
; CHECK-NEXT: nds.bfoz a0, a0, 25, 48
145+
; CHECK-NEXT: ret
146+
%shl = shl i64 %x, 40
147+
%lshr = lshr i64 %shl, 15
148+
ret i64 %lshr
149+
}
150+
151+
; NDS.BFOS
152+
153+
; MSB >= LSB
154+
63155
define i32 @bfos_from_ashr_shl_i32(i32 %x) {
64156
; CHECK-LABEL: bfos_from_ashr_shl_i32:
65157
; CHECK: # %bb.0:

llvm/test/CodeGen/RISCV/rv64zba.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ define i64 @slliuw(i64 %a) nounwind {
2424
;
2525
; RV64XANDESPERF-LABEL: slliuw:
2626
; RV64XANDESPERF: # %bb.0:
27-
; RV64XANDESPERF-NEXT: slli a0, a0, 32
28-
; RV64XANDESPERF-NEXT: srli a0, a0, 31
27+
; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 1, 32
2928
; RV64XANDESPERF-NEXT: ret
3029
%conv1 = shl i64 %a, 1
3130
%shl = and i64 %conv1, 8589934590

0 commit comments

Comments
 (0)