-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[RISCV] Select signed bitfield extracts for XAndesPerf #142303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The XAndesPerf extension includes signed bitfield extraction instruction `NDS.BFOS`, which can extract the bits from LSB to MSB, places them starting at bit 0, and sign-extends the result. The testcase includes the two patterns that can be selected as signed bitfield extracts: `ashr+shl` and `ashr+sext_inreg`
@llvm/pr-subscribers-backend-risc-v Author: Jim Lin (tclin914) ChangesThe XAndesPerf extension includes signed bitfield extraction The testcase includes the two patterns that can be selected as Full diff: https://github.com/llvm/llvm-project/pull/142303.diff 3 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 2de22ee165aea..4f6aa41d1e03b 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -601,8 +601,8 @@ bool RISCVDAGToDAGISel::tryShrinkShlLogicImm(SDNode *Node) {
}
bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
- // Only supported with XTHeadBb at the moment.
- if (!Subtarget->hasVendorXTHeadBb())
+ // Only supported with XTHeadBb/XAndesPerf at the moment.
+ if (!Subtarget->hasVendorXTHeadBb() && !Subtarget->hasVendorXAndesPerf())
return false;
auto *N1C = dyn_cast<ConstantSDNode>(Node->getOperand(1));
@@ -615,7 +615,9 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) {
auto BitfieldExtract = [&](SDValue N0, unsigned Msb, unsigned Lsb, SDLoc DL,
MVT VT) {
- return CurDAG->getMachineNode(RISCV::TH_EXT, DL, VT, N0.getOperand(0),
+ unsigned Opc =
+ Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXT : RISCV::NDS_BFOS;
+ return CurDAG->getMachineNode(Opc, DL, VT, N0.getOperand(0),
CurDAG->getTargetConstant(Msb, DL, VT),
CurDAG->getTargetConstant(Lsb, DL, VT));
};
diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
index 72dddddf9f382..af353a1e541fe 100644
--- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll
@@ -70,6 +70,86 @@ define i64 @bfoz_from_lshr_and_i64(i64 %x) {
ret i64 %shifted
}
+define i32 @bfos_from_ashr_shl_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 23, 16
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 8
+ %ashr = ashr i32 %shl, 24
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_shl_i64(i64 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x12 killed $x11
+; CHECK-NEXT: # kill: def $x12 killed $x10
+; CHECK-NEXT: srli a2, a0, 24
+; CHECK-NEXT: slli a1, a1, 8
+; CHECK-NEXT: or a2, a1, a2
+; CHECK-NEXT: slli a2, a2, 8
+; CHECK-NEXT: nds.bfoz a0, a0, 23, 16
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: srai a1, a1, 24
+; CHECK-NEXT: ret
+ %shl = shl i64 %x, 8
+ %ashr = ashr i64 %shl, 24
+ ret i64 %ashr
+}
+
+define i32 @bfos_from_ashr_sexti8_i32(i8 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti8_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: nds.bfos a0, a0, 7, 5
+; CHECK-NEXT: ret
+ %sext = sext i8 %x to i32
+ %ashr = ashr i32 %sext, 5
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_sexti8_i64(i8 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti8_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: nds.bfos a0, a0, 7, 0
+; CHECK-NEXT: srai a1, a0, 31
+; CHECK-NEXT: srli a0, a0, 5
+; CHECK-NEXT: slli a2, a1, 27
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: ret
+ %sext = sext i8 %x to i64
+ %ashr = ashr i64 %sext, 5
+ ret i64 %ashr
+}
+
+define i32 @bfos_from_ashr_sexti16_i32(i16 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti16_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: nds.bfos a0, a0, 15, 11
+; CHECK-NEXT: ret
+ %sext = sext i16 %x to i32
+ %ashr = ashr i32 %sext, 11
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_sexti16_i64(i16 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti16_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: # kill: def $x11 killed $x10
+; CHECK-NEXT: nds.bfos a0, a0, 15, 0
+; CHECK-NEXT: srai a1, a0, 31
+; CHECK-NEXT: srli a0, a0, 11
+; CHECK-NEXT: slli a2, a1, 21
+; CHECK-NEXT: or a0, a0, a2
+; CHECK-NEXT: ret
+ %sext = sext i16 %x to i64
+ %ashr = ashr i64 %sext, 11
+ ret i64 %ashr
+}
+
define i32 @sexti1_i32(i32 %a) {
; CHECK-LABEL: sexti1_i32:
; CHECK: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
index 13c2234071eb1..260d30be686dc 100644
--- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
+++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll
@@ -60,6 +60,66 @@ define i64 @bfoz_from_lshr_and_i64(i64 %x) {
ret i64 %shifted
}
+define i32 @bfos_from_ashr_shl_i32(i32 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 23, 16
+; CHECK-NEXT: ret
+ %shl = shl i32 %x, 8
+ %ashr = ashr i32 %shl, 24
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_shl_i64(i64 %x) {
+; CHECK-LABEL: bfos_from_ashr_shl_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 55, 16
+; CHECK-NEXT: ret
+ %shl = shl i64 %x, 8
+ %ashr = ashr i64 %shl, 24
+ ret i64 %ashr
+}
+
+define i32 @bfos_from_ashr_sexti8_i32(i8 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti8_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 7, 5
+; CHECK-NEXT: ret
+ %sext = sext i8 %x to i32
+ %ashr = ashr i32 %sext, 5
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_sexti8_i64(i8 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti8_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 7, 5
+; CHECK-NEXT: ret
+ %sext = sext i8 %x to i64
+ %ashr = ashr i64 %sext, 5
+ ret i64 %ashr
+}
+
+define i32 @bfos_from_ashr_sexti16_i32(i16 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti16_i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 15, 11
+; CHECK-NEXT: ret
+ %sext = sext i16 %x to i32
+ %ashr = ashr i32 %sext, 11
+ ret i32 %ashr
+}
+
+define i64 @bfos_from_ashr_sexti16_i64(i16 %x) {
+; CHECK-LABEL: bfos_from_ashr_sexti16_i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: nds.bfos a0, a0, 15, 11
+; CHECK-NEXT: ret
+ %sext = sext i16 %x to i64
+ %ashr = ashr i64 %sext, 11
+ ret i64 %ashr
+}
+
define signext i32 @sexti1_i32(i32 signext %a) {
; CHECK-LABEL: sexti1_i32:
; CHECK: # %bb.0:
|
; CHECK-NEXT: slli a2, a1, 21 | ||
; CHECK-NEXT: or a0, a0, a2 | ||
; CHECK-NEXT: ret | ||
%sext = sext i16 %x to i64 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this supposed to use nds.bfos or was it a negative test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unnecessary. Thanks. Remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
The XAndesPerf extension includes signed bitfield extraction instruction `NDS.BFOS`, which can extract the bits from LSB to MSB, places them starting at bit 0, and sign-extends the result. The testcase includes the two patterns that can be selected as signed bitfield extracts: `ashr+shl` and `ashr+sext_inreg`
The XAndesPerf extension includes signed bitfield extraction
instruction
NDS.BFOS
, which can extract the bits from LSB to MSB,places them starting at bit 0, and sign-extends the result.
The testcase includes the two patterns that can be selected as
signed bitfield extracts:
ashr+shl
andashr+sext_inreg