diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 18af1545d5a34..306da41a9c8e4 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -672,14 +672,17 @@ bool RISCVDAGToDAGISel::trySignedBitfieldExtract(SDNode *Node) { bool RISCVDAGToDAGISel::tryUnsignedBitfieldExtract(SDNode *Node, SDLoc DL, MVT VT, SDValue X, unsigned Msb, unsigned Lsb) { - // 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; - SDNode *TH_EXTU = CurDAG->getMachineNode( - RISCV::TH_EXTU, DL, VT, X, CurDAG->getTargetConstant(Msb, DL, VT), - CurDAG->getTargetConstant(Lsb, DL, VT)); - ReplaceNode(Node, TH_EXTU); + unsigned Opc = + Subtarget->hasVendorXTHeadBb() ? RISCV::TH_EXTU : RISCV::NDS_BFOZ; + + SDNode *Ube = CurDAG->getMachineNode(Opc, DL, VT, X, + CurDAG->getTargetConstant(Msb, DL, VT), + CurDAG->getTargetConstant(Lsb, DL, VT)); + ReplaceNode(Node, Ube); return true; } diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll index efe5b4a306fee..72dddddf9f382 100644 --- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll @@ -2,6 +2,74 @@ ; RUN: llc -O0 -mtriple=riscv32 -mattr=+xandesperf -verify-machineinstrs < %s \ ; RUN: | FileCheck %s +define i32 @bfoz_from_and_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_and_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 11, 0 +; CHECK-NEXT: ret + %a = and i32 %x, 4095 + ret i32 %a +} + +define i64 @bfoz_from_and_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_and_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $x11 killed $x10 +; CHECK-NEXT: nds.bfoz a0, a0, 11, 0 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %a = and i64 %x, 4095 + ret i64 %a +} + +define i32 @bfoz_from_and_lshr_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_and_lshr_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 25, 23 +; CHECK-NEXT: ret + %shifted = lshr i32 %x, 23 + %masked = and i32 %shifted, 7 + ret i32 %masked +} + +define i64 @bfoz_from_and_lshr_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_and_lshr_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $x12 killed $x11 +; CHECK-NEXT: nds.bfoz a0, a1, 25, 14 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %shifted = lshr i64 %x, 46 + %masked = and i64 %shifted, 4095 + ret i64 %masked +} + +define i32 @bfoz_from_lshr_and_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_lshr_and_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 23, 12 +; CHECK-NEXT: ret + %masked = and i32 %x, 16773120 + %shifted = lshr i32 %masked, 12 + ret i32 %shifted +} + +define i64 @bfoz_from_lshr_and_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_lshr_and_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: # kill: def $x12 killed $x11 +; CHECK-NEXT: # kill: def $x12 killed $x10 +; CHECK-NEXT: andi a1, a1, 15 +; CHECK-NEXT: srli a0, a0, 24 +; CHECK-NEXT: slli a1, a1, 8 +; CHECK-NEXT: or a0, a0, a1 +; CHECK-NEXT: li a1, 0 +; CHECK-NEXT: ret + %masked = and i64 %x, 68702699520 + %shifted = lshr i64 %masked, 24 + ret i64 %shifted +} + 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 9cc95ce886133..13c2234071eb1 100644 --- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll @@ -2,6 +2,64 @@ ; RUN: llc -mtriple=riscv64 -mattr=+xandesperf -verify-machineinstrs < %s \ ; RUN: | FileCheck %s +define i32 @bfoz_from_and_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_and_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 11, 0 +; CHECK-NEXT: ret + %a = and i32 %x, 4095 + ret i32 %a +} + +define i64 @bfoz_from_and_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_and_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 11, 0 +; CHECK-NEXT: ret + %a = and i64 %x, 4095 + ret i64 %a +} + +define i32 @bfoz_from_and_lshr_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_and_lshr_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 25, 23 +; CHECK-NEXT: ret + %shifted = lshr i32 %x, 23 + %masked = and i32 %shifted, 7 + ret i32 %masked +} + +define i64 @bfoz_from_and_lshr_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_and_lshr_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 57, 46 +; CHECK-NEXT: ret + %shifted = lshr i64 %x, 46 + %masked = and i64 %shifted, 4095 + ret i64 %masked +} + +define i32 @bfoz_from_lshr_and_i32(i32 %x) { +; CHECK-LABEL: bfoz_from_lshr_and_i32: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 23, 12 +; CHECK-NEXT: ret + %masked = and i32 %x, 16773120 + %shifted = lshr i32 %masked, 12 + ret i32 %shifted +} + +define i64 @bfoz_from_lshr_and_i64(i64 %x) { +; CHECK-LABEL: bfoz_from_lshr_and_i64: +; CHECK: # %bb.0: +; CHECK-NEXT: nds.bfoz a0, a0, 35, 24 +; CHECK-NEXT: ret + %masked = and i64 %x, 68702699520 + %shifted = lshr i64 %masked, 24 + ret i64 %shifted +} + define signext i32 @sexti1_i32(i32 signext %a) { ; CHECK-LABEL: sexti1_i32: ; CHECK: # %bb.0: diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll index 6bd808ca9e126..622b302da4c51 100644 --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -126,7 +126,7 @@ define i64 @zextw_i64(i64 %a) nounwind { ; ; RV64XANDESPERF-LABEL: zextw_i64: ; RV64XANDESPERF: # %bb.0: -; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, zero, a0 +; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 31, 0 ; RV64XANDESPERF-NEXT: ret %and = and i64 %a, 4294967295 ret i64 %and @@ -151,7 +151,7 @@ define i64 @zextw_demandedbits_i64(i64 %0) { ; RV64XANDESPERF-LABEL: zextw_demandedbits_i64: ; RV64XANDESPERF: # %bb.0: ; RV64XANDESPERF-NEXT: ori a0, a0, 1 -; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, zero, a0 +; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 31, 0 ; RV64XANDESPERF-NEXT: ret %2 = and i64 %0, 4294967294 %3 = or i64 %2, 1 @@ -1577,7 +1577,7 @@ define i64 @adduw_imm(i32 signext %0) nounwind { ; ; RV64XANDESPERF-LABEL: adduw_imm: ; RV64XANDESPERF: # %bb.0: -; RV64XANDESPERF-NEXT: nds.lea.b.ze a0, zero, a0 +; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 31, 0 ; RV64XANDESPERF-NEXT: addi a0, a0, 5 ; RV64XANDESPERF-NEXT: ret %a = zext i32 %0 to i64 @@ -2324,8 +2324,7 @@ define zeroext i32 @sext_ashr_zext_i8(i8 %a) nounwind { ; RV64XANDESPERF-LABEL: sext_ashr_zext_i8: ; RV64XANDESPERF: # %bb.0: ; RV64XANDESPERF-NEXT: nds.bfos a0, a0, 7, 0 -; RV64XANDESPERF-NEXT: slli a0, a0, 23 -; RV64XANDESPERF-NEXT: srli a0, a0, 32 +; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 40, 9 ; RV64XANDESPERF-NEXT: ret %ext = sext i8 %a to i32 %1 = ashr i32 %ext, 9 @@ -2473,8 +2472,7 @@ define zeroext i32 @sext_ashr_zext_i16(i16 %a) nounwind { ; RV64XANDESPERF-LABEL: sext_ashr_zext_i16: ; RV64XANDESPERF: # %bb.0: ; RV64XANDESPERF-NEXT: nds.bfos a0, a0, 15, 0 -; RV64XANDESPERF-NEXT: slli a0, a0, 23 -; RV64XANDESPERF-NEXT: srli a0, a0, 32 +; RV64XANDESPERF-NEXT: nds.bfoz a0, a0, 40, 9 ; RV64XANDESPERF-NEXT: ret %ext = sext i16 %a to i32 %1 = ashr i32 %ext, 9