Skip to content

Commit 2e336d7

Browse files
tclin914tomtor
authored andcommitted
[RISCV] Select signed bitfield insert for XAndesPerf (llvm#143356)
This patch is similar to llvm#142737 The XAndesPerf extension includes signed bitfield extraction instruction `NDS.BFOS, which can extract the bits from 0 to Len - 1, place them starting at bit Lsb, zero-filled the bits from 0 to Lsb -1, and sign-extend the result. When Lsb == Msb, it is a special case where the Lsb will be set to 0 instead of being equal to the Msb.
1 parent 521ff2a commit 2e336d7

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,59 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
683683
return false;
684684
}
685685

686+
bool RISCVDAGToDAGISel::trySignedBitfieldInsertInSign(SDNode *Node) {
687+
// Only supported with XAndesPerf at the moment.
688+
if (!Subtarget->hasVendorXAndesPerf())
689+
return false;
690+
691+
auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
692+
if (!N1C)
693+
return false;
694+
695+
SDValue N0 = Node->getOperand(0);
696+
if (!N0.hasOneUse())
697+
return false;
698+
699+
auto BitfieldInsert = [&](SDValue N0, unsigned Msb, unsigned Lsb,
700+
const SDLoc &DL, MVT VT) {
701+
unsigned Opc = RISCV::NDS_BFOS;
702+
// If the Lsb is equal to the Msb, then the Lsb should be 0.
703+
if (Lsb == Msb)
704+
Lsb = 0;
705+
return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
706+
CurDAG->getTargetConstant(Lsb, DL, VT),
707+
CurDAG->getTargetConstant(Msb, DL, VT));
708+
};
709+
710+
SDLoc DL(Node);
711+
MVT VT = Node->getSimpleValueType(0);
712+
const unsigned RightShAmt = N1C->getZExtValue();
713+
714+
// Transform (sra (shl X, C1) C2) with C1 > C2
715+
// -> (NDS.BFOS X, lsb, msb)
716+
if (N0.getOpcode() == ISD::SHL) {
717+
auto *N01C = dyn_cast<ConstantSDNode>(N0->getOperand(1));
718+
if (!N01C)
719+
return false;
720+
721+
const unsigned LeftShAmt = N01C->getZExtValue();
722+
// Make sure that this is a bitfield insertion (i.e., the shift-right
723+
// amount should be less than the left-shift).
724+
if (LeftShAmt <= RightShAmt)
725+
return false;
726+
727+
const unsigned MsbPlusOne = VT.getSizeInBits() - RightShAmt;
728+
const unsigned Msb = MsbPlusOne - 1;
729+
const unsigned Lsb = LeftShAmt - RightShAmt;
730+
731+
SDNode *Sbi = BitfieldInsert(N0, Msb, Lsb, DL, VT);
732+
ReplaceNode(Node, Sbi);
733+
return true;
734+
}
735+
736+
return false;
737+
}
738+
686739
bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node,
687740
const SDLoc &DL, MVT VT,
688741
SDValue X, unsigned Msb,
@@ -1214,6 +1267,9 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
12141267
if (trySignedBitfieldExtract(Node))
12151268
return;
12161269

1270+
if (trySignedBitfieldInsertInSign(Node))
1271+
return;
1272+
12171273
// Optimize (sra (sext_inreg X, i16), C) ->
12181274
// (srai (slli X, (XLen-16), (XLen-16) + C)
12191275
// And (sra (sext_inreg X, i8), C) ->

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
7777

7878
bool tryShrinkShlLogicImm(SDNode *Node);
7979
bool trySignedBitfieldExtract(SDNode *Node);
80+
bool trySignedBitfieldInsertInSign(SDNode *Node);
8081
bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT,
8182
SDValue X, unsigned Msb, unsigned Lsb);
8283
bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT,

llvm/test/CodeGen/RISCV/rv32xandesperf.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,32 @@ define i32 @bfos_from_ashr_sexti16_i32(i16 %x) {
154154
ret i32 %ashr
155155
}
156156

157+
; MSB = 0
158+
159+
define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
160+
; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i32:
161+
; CHECK: # %bb.0:
162+
; CHECK-NEXT: nds.bfos a0, a0, 0, 14
163+
; CHECK-NEXT: ret
164+
%shl = shl i32 %x, 31
165+
%lshr = ashr i32 %shl, 17
166+
ret i32 %lshr
167+
}
168+
169+
; MSB < LSB
170+
171+
define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
172+
; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
173+
; CHECK: # %bb.0:
174+
; CHECK-NEXT: nds.bfos a0, a0, 18, 20
175+
; CHECK-NEXT: ret
176+
%shl = shl i32 %x, 29
177+
%lshr = ashr i32 %shl, 11
178+
ret i32 %lshr
179+
}
180+
181+
; sext
182+
157183
define i32 @sexti1_i32(i32 %a) {
158184
; CHECK-LABEL: sexti1_i32:
159185
; CHECK: # %bb.0:

llvm/test/CodeGen/RISCV/rv64xandesperf.ll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,52 @@ define i64 @bfos_from_ashr_sexti16_i64(i16 %x) {
212212
ret i64 %ashr
213213
}
214214

215+
; MSB = 0
216+
217+
define i32 @bfos_from_ashr_shl_with_msb_zero_insert_i32(i32 %x) {
218+
; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i32:
219+
; CHECK: # %bb.0:
220+
; CHECK-NEXT: nds.bfos a0, a0, 0, 14
221+
; CHECK-NEXT: ret
222+
%shl = shl i32 %x, 31
223+
%lshr = ashr i32 %shl, 17
224+
ret i32 %lshr
225+
}
226+
227+
define i64 @bfos_from_ashr_shl_with_msb_zero_insert_i64(i64 %x) {
228+
; CHECK-LABEL: bfos_from_ashr_shl_with_msb_zero_insert_i64:
229+
; CHECK: # %bb.0:
230+
; CHECK-NEXT: nds.bfos a0, a0, 0, 46
231+
; CHECK-NEXT: ret
232+
%shl = shl i64 %x, 63
233+
%lshr = ashr i64 %shl, 17
234+
ret i64 %lshr
235+
}
236+
237+
; MSB < LSB
238+
239+
define i32 @bfos_from_ashr_shl_insert_i32(i32 %x) {
240+
; CHECK-LABEL: bfos_from_ashr_shl_insert_i32:
241+
; CHECK: # %bb.0:
242+
; CHECK-NEXT: nds.bfos a0, a0, 18, 20
243+
; CHECK-NEXT: ret
244+
%shl = shl i32 %x, 29
245+
%lshr = ashr i32 %shl, 11
246+
ret i32 %lshr
247+
}
248+
249+
define i64 @bfos_from_ashr_shl_insert_i64(i64 %x) {
250+
; CHECK-LABEL: bfos_from_ashr_shl_insert_i64:
251+
; CHECK: # %bb.0:
252+
; CHECK-NEXT: nds.bfos a0, a0, 18, 52
253+
; CHECK-NEXT: ret
254+
%shl = shl i64 %x, 29
255+
%lshr = ashr i64 %shl, 11
256+
ret i64 %lshr
257+
}
258+
259+
; sext
260+
215261
define signext i32 @sexti1_i32(i32 signext %a) {
216262
; CHECK-LABEL: sexti1_i32:
217263
; CHECK: # %bb.0:

0 commit comments

Comments
 (0)