diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -1372,17 +1372,40 @@ if (CN->getZExtValue() <= 0xfff) return SDValue(); - // Return if the mask doesn't start at position 0. - if (SMIdx) + // Return if the MSB exceeds. + if (SMIdx + SMLen > ValTy.getSizeInBits()) return SDValue(); + if (SMIdx > 0) { + // Return if the constant has multiple uses. + if (!CN->hasOneUse()) + return SDValue(); + // Return if the constant can be composed by a single LU12I.W. + if ((CN->getZExtValue() & 0xfff) == 0) + return SDValue(); + // Return if the constand can be composed by a single ADDI with + // the zero register. + if (CN->getSExtValue() >= -2048 && CN->getSExtValue() < 0) + return SDValue(); + } + lsb = 0; NewOperand = FirstOperand; } + msb = lsb + SMLen - 1; - return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, - DAG.getConstant(msb, DL, GRLenVT), - DAG.getConstant(lsb, DL, GRLenVT)); + SDValue NR0 = DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy, NewOperand, + DAG.getConstant(msb, DL, GRLenVT), + DAG.getConstant(lsb, DL, GRLenVT)); + + if (FirstOperandOpc == ISD::SRA || FirstOperandOpc == ISD::SRL || SMIdx == 0) + return NR0; + + // Try to optimize to + // bstrpick $Rd, $Rs, msb, lsb + // slli $Rd, $Rd, SMIdx + return DAG.getNode(ISD::SHL, DL, ValTy, NR0, + DAG.getConstant(SMIdx, DL, GRLenVT)); } static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG, diff --git a/llvm/test/CodeGen/LoongArch/alloca.ll b/llvm/test/CodeGen/LoongArch/alloca.ll --- a/llvm/test/CodeGen/LoongArch/alloca.ll +++ b/llvm/test/CodeGen/LoongArch/alloca.ll @@ -34,11 +34,10 @@ ; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ; LA64-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill ; LA64-NEXT: addi.d $fp, $sp, 16 -; LA64-NEXT: addi.w $a1, $zero, -16 -; LA64-NEXT: lu32i.d $a1, 1 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: addi.d $a0, $a0, 15 -; LA64-NEXT: and $a0, $a0, $a1 +; LA64-NEXT: bstrpick.d $a0, $a0, 28, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: move $sp, $a0 ; LA64-NEXT: bl %plt(notdead) @@ -85,12 +84,11 @@ ; LA64-NEXT: st.d $fp, $sp, 16 # 8-byte Folded Spill ; LA64-NEXT: st.d $s0, $sp, 8 # 8-byte Folded Spill ; LA64-NEXT: addi.d $fp, $sp, 32 -; LA64-NEXT: addi.w $a1, $zero, -16 -; LA64-NEXT: lu32i.d $a1, 1 +; LA64-NEXT: move $s0, $sp ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: addi.d $a0, $a0, 15 -; LA64-NEXT: and $a0, $a0, $a1 -; LA64-NEXT: move $s0, $sp +; LA64-NEXT: bstrpick.d $a0, $a0, 28, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: move $sp, $a0 ; LA64-NEXT: bl %plt(notdead) @@ -154,11 +152,10 @@ ; LA64-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ; LA64-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill ; LA64-NEXT: addi.d $fp, $sp, 16 -; LA64-NEXT: addi.w $a1, $zero, -16 -; LA64-NEXT: lu32i.d $a1, 1 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: addi.d $a0, $a0, 15 -; LA64-NEXT: and $a0, $a0, $a1 +; LA64-NEXT: bstrpick.d $a0, $a0, 28, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: move $sp, $a0 ; LA64-NEXT: addi.d $sp, $sp, -32 diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll --- a/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll +++ b/llvm/test/CodeGen/LoongArch/ir-instruction/and.ll @@ -269,16 +269,14 @@ define signext i32 @and_i32_0xfff0(i32 %a) { ; LA32-LABEL: and_i32_0xfff0: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, 15 -; LA32-NEXT: ori $a1, $a1, 4080 -; LA32-NEXT: and $a0, $a0, $a1 +; LA32-NEXT: bstrpick.w $a0, $a0, 11, 0 +; LA32-NEXT: slli.w $a0, $a0, 4 ; LA32-NEXT: ret ; ; LA64-LABEL: and_i32_0xfff0: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 15 -; LA64-NEXT: ori $a1, $a1, 4080 -; LA64-NEXT: and $a0, $a0, $a1 +; LA64-NEXT: bstrpick.d $a0, $a0, 11, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: ret %b = and i32 %a, 65520 ret i32 %b @@ -303,17 +301,15 @@ define i64 @and_i64_0xfff0(i64 %a) { ; LA32-LABEL: and_i64_0xfff0: ; LA32: # %bb.0: -; LA32-NEXT: lu12i.w $a1, 15 -; LA32-NEXT: ori $a1, $a1, 4080 -; LA32-NEXT: and $a0, $a0, $a1 +; LA32-NEXT: bstrpick.w $a0, $a0, 11, 0 +; LA32-NEXT: slli.w $a0, $a0, 4 ; LA32-NEXT: move $a1, $zero ; LA32-NEXT: ret ; ; LA64-LABEL: and_i64_0xfff0: ; LA64: # %bb.0: -; LA64-NEXT: lu12i.w $a1, 15 -; LA64-NEXT: ori $a1, $a1, 4080 -; LA64-NEXT: and $a0, $a0, $a1 +; LA64-NEXT: bstrpick.d $a0, $a0, 11, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: ret %b = and i64 %a, 65520 ret i64 %b diff --git a/llvm/test/CodeGen/LoongArch/shrinkwrap.ll b/llvm/test/CodeGen/LoongArch/shrinkwrap.ll --- a/llvm/test/CodeGen/LoongArch/shrinkwrap.ll +++ b/llvm/test/CodeGen/LoongArch/shrinkwrap.ll @@ -60,11 +60,10 @@ ; NOSHRINKW-NEXT: b .LBB1_1 ; NOSHRINKW-NEXT: .LBB1_1: # %if.then ; NOSHRINKW-NEXT: ld.d $a0, $fp, -24 # 8-byte Folded Reload -; NOSHRINKW-NEXT: addi.w $a1, $zero, -16 -; NOSHRINKW-NEXT: lu32i.d $a1, 1 ; NOSHRINKW-NEXT: bstrpick.d $a0, $a0, 31, 0 ; NOSHRINKW-NEXT: addi.d $a0, $a0, 15 -; NOSHRINKW-NEXT: and $a1, $a0, $a1 +; NOSHRINKW-NEXT: bstrpick.d $a0, $a0, 28, 0 +; NOSHRINKW-NEXT: slli.d $a1, $a0, 4 ; NOSHRINKW-NEXT: move $a0, $sp ; NOSHRINKW-NEXT: sub.d $a0, $a0, $a1 ; NOSHRINKW-NEXT: move $sp, $a0 @@ -87,10 +86,9 @@ ; SHRINKW-NEXT: st.d $ra, $sp, 8 # 8-byte Folded Spill ; SHRINKW-NEXT: st.d $fp, $sp, 0 # 8-byte Folded Spill ; SHRINKW-NEXT: addi.d $fp, $sp, 16 -; SHRINKW-NEXT: addi.w $a1, $zero, -16 -; SHRINKW-NEXT: lu32i.d $a1, 1 ; SHRINKW-NEXT: addi.d $a0, $a0, 15 -; SHRINKW-NEXT: and $a0, $a0, $a1 +; SHRINKW-NEXT: bstrpick.d $a0, $a0, 28, 0 +; SHRINKW-NEXT: slli.d $a0, $a0, 4 ; SHRINKW-NEXT: sub.d $a0, $sp, $a0 ; SHRINKW-NEXT: move $sp, $a0 ; SHRINKW-NEXT: bl %plt(notdead) diff --git a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll --- a/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll +++ b/llvm/test/CodeGen/LoongArch/stack-realignment-with-variable-sized-objects.ll @@ -51,11 +51,10 @@ ; LA64-NEXT: srli.d $a1, $sp, 6 ; LA64-NEXT: slli.d $sp, $a1, 6 ; LA64-NEXT: move $s8, $sp -; LA64-NEXT: addi.w $a1, $zero, -16 -; LA64-NEXT: lu32i.d $a1, 1 ; LA64-NEXT: bstrpick.d $a0, $a0, 31, 0 ; LA64-NEXT: addi.d $a0, $a0, 15 -; LA64-NEXT: and $a0, $a0, $a1 +; LA64-NEXT: bstrpick.d $a0, $a0, 28, 0 +; LA64-NEXT: slli.d $a0, $a0, 4 ; LA64-NEXT: sub.d $a0, $sp, $a0 ; LA64-NEXT: move $sp, $a0 ; LA64-NEXT: addi.d $a1, $s8, 0