Skip to content

Commit 34b985f

Browse files
authored
[RISCV] Select unsigned bitfield extract for Xqcibm (#143354)
The Xqcibm Bit Manipulation extension has the `qc.extu` instruction that can extract a subset of bits from the source register to the destination register. Unlike the corresponding instructions in XTHeadbb and XAndesPerf which extract the bits between `Msb` and `Lsb`, the `qc.extu` instruction extracts `width` bits from an offset that is determined by the `shamt`.
1 parent 0123ee5 commit 34b985f

File tree

2 files changed

+115
-5
lines changed

2 files changed

+115
-5
lines changed

llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -675,12 +675,22 @@ bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node,
675675
const SDLoc &DL, MVT VT,
676676
SDValue X, unsigned Msb,
677677
unsigned Lsb) {
678-
// Only supported with XTHeadBb/XAndesPerf at the moment.
679-
if (!Subtarget->hasVendorXTHeadBb() && !Subtarget->hasVendorXAndesPerf())
678+
unsigned Opc;
679+
680+
if (Subtarget->hasVendorXTHeadBb()) {
681+
Opc = RISCV::TH_EXTU;
682+
} else if (Subtarget->hasVendorXAndesPerf()) {
683+
Opc = RISCV::NDS_BFOZ;
684+
} else if (Subtarget->hasVendorXqcibm()) {
685+
Opc = RISCV::QC_EXTU;
686+
// QC.EXTU X, width, shamt
687+
// shamt is the same as Lsb
688+
// width is the number of bits to extract from the Lsb
689+
Msb = Msb - Lsb + 1;
690+
} else {
691+
// Only supported with XTHeadBb/XAndesPerf/Xqcibm at the moment.
680692
return false;
681-
682-
unsigned Opc =
683-
Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXTU : RISCV::NDS_BFOZ;
693+
}
684694

685695
SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X,
686696
CurDAG->getTargetConstant(Msb, DL, VT),

llvm/test/CodeGen/RISCV/xqcibm-extract.ll

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,103 @@ define i64 @sexti32_i64_2(i32 %a) {
231231
%1 = sext i32 %a to i64
232232
ret i64 %1
233233
}
234+
235+
define i32 @extu_from_and_i32(i32 %x) {
236+
; RV32I-LABEL: extu_from_and_i32:
237+
; RV32I: # %bb.0:
238+
; RV32I-NEXT: slli a0, a0, 20
239+
; RV32I-NEXT: srli a0, a0, 20
240+
; RV32I-NEXT: ret
241+
;
242+
; RV32XQCIBM-LABEL: extu_from_and_i32:
243+
; RV32XQCIBM: # %bb.0:
244+
; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 0
245+
; RV32XQCIBM-NEXT: ret
246+
%a = and i32 %x, 4095
247+
ret i32 %a
248+
}
249+
250+
define i64 @extu_from_and_i64(i64 %x) {
251+
; RV32I-LABEL: extu_from_and_i64:
252+
; RV32I: # %bb.0:
253+
; RV32I-NEXT: slli a0, a0, 20
254+
; RV32I-NEXT: srli a0, a0, 20
255+
; RV32I-NEXT: li a1, 0
256+
; RV32I-NEXT: ret
257+
;
258+
; RV32XQCIBM-LABEL: extu_from_and_i64:
259+
; RV32XQCIBM: # %bb.0:
260+
; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 0
261+
; RV32XQCIBM-NEXT: li a1, 0
262+
; RV32XQCIBM-NEXT: ret
263+
%a = and i64 %x, 4095
264+
ret i64 %a
265+
}
266+
267+
define i32 @extu_from_and_lshr_i32(i32 %x) {
268+
; RV32I-LABEL: extu_from_and_lshr_i32:
269+
; RV32I: # %bb.0:
270+
; RV32I-NEXT: slli a0, a0, 6
271+
; RV32I-NEXT: srli a0, a0, 29
272+
; RV32I-NEXT: ret
273+
;
274+
; RV32XQCIBM-LABEL: extu_from_and_lshr_i32:
275+
; RV32XQCIBM: # %bb.0:
276+
; RV32XQCIBM-NEXT: qc.extu a0, a0, 3, 23
277+
; RV32XQCIBM-NEXT: ret
278+
%shifted = lshr i32 %x, 23
279+
%masked = and i32 %shifted, 7
280+
ret i32 %masked
281+
}
282+
283+
define i64 @extu_from_and_lshr_i64(i64 %x) {
284+
; RV32I-LABEL: extu_from_and_lshr_i64:
285+
; RV32I: # %bb.0:
286+
; RV32I-NEXT: slli a0, a1, 6
287+
; RV32I-NEXT: srli a0, a0, 20
288+
; RV32I-NEXT: li a1, 0
289+
; RV32I-NEXT: ret
290+
;
291+
; RV32XQCIBM-LABEL: extu_from_and_lshr_i64:
292+
; RV32XQCIBM: # %bb.0:
293+
; RV32XQCIBM-NEXT: qc.extu a0, a1, 12, 14
294+
; RV32XQCIBM-NEXT: li a1, 0
295+
; RV32XQCIBM-NEXT: ret
296+
%shifted = lshr i64 %x, 46
297+
%masked = and i64 %shifted, 4095
298+
ret i64 %masked
299+
}
300+
301+
define i32 @extu_from_lshr_and_i32(i32 %x) {
302+
; RV32I-LABEL: extu_from_lshr_and_i32:
303+
; RV32I: # %bb.0:
304+
; RV32I-NEXT: slli a0, a0, 8
305+
; RV32I-NEXT: srli a0, a0, 20
306+
; RV32I-NEXT: ret
307+
;
308+
; RV32XQCIBM-LABEL: extu_from_lshr_and_i32:
309+
; RV32XQCIBM: # %bb.0:
310+
; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 12
311+
; RV32XQCIBM-NEXT: ret
312+
%masked = and i32 %x, 16773120
313+
%shifted = lshr i32 %masked, 12
314+
ret i32 %shifted
315+
}
316+
317+
define i64 @extu_from_lshr_and_i64(i64 %x) {
318+
; RV32I-LABEL: extu_from_lshr_and_i64:
319+
; RV32I: # %bb.0:
320+
; RV32I-NEXT: slli a0, a0, 8
321+
; RV32I-NEXT: srli a0, a0, 20
322+
; RV32I-NEXT: li a1, 0
323+
; RV32I-NEXT: ret
324+
;
325+
; RV32XQCIBM-LABEL: extu_from_lshr_and_i64:
326+
; RV32XQCIBM: # %bb.0:
327+
; RV32XQCIBM-NEXT: qc.extu a0, a0, 12, 12
328+
; RV32XQCIBM-NEXT: li a1, 0
329+
; RV32XQCIBM-NEXT: ret
330+
%masked = and i64 %x, 16773120
331+
%shifted = lshr i64 %masked, 12
332+
ret i64 %shifted
333+
}

0 commit comments

Comments
 (0)