[llvm] [LoongArch] Optimize codegen for ISD::ROTL (PR #91174)
via llvm-commits
llvm-commits at lists.llvm.org
Mon May 6 01:53:53 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: hev (heiher)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/91174.diff
3 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+25-10)
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.td (+2-5)
- (modified) llvm/test/CodeGen/LoongArch/rotl-rotr.ll (+13-20)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 46a6703f29d500..5c61db760f8562 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -79,6 +79,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SRL_PARTS, GRLenVT, Custom);
setOperationAction(ISD::FP_TO_SINT, GRLenVT, Custom);
setOperationAction(ISD::ROTL, GRLenVT, Expand);
+ setOperationAction(ISD::ROTR, GRLenVT, Legal);
setOperationAction(ISD::CTPOP, GRLenVT, Expand);
setOperationAction({ISD::GlobalAddress, ISD::BlockAddress, ISD::ConstantPool,
@@ -1671,10 +1672,6 @@ static LoongArchISD::NodeType getLoongArchWOpcode(unsigned Opcode) {
return LoongArchISD::SRA_W;
case ISD::SRL:
return LoongArchISD::SRL_W;
- case ISD::ROTR:
- return LoongArchISD::ROTR_W;
- case ISD::ROTL:
- return LoongArchISD::ROTL_W;
case ISD::CTTZ:
return LoongArchISD::CTZ_W;
case ISD::CTLZ:
@@ -1715,6 +1712,26 @@ static SDValue customLegalizeToWOp(SDNode *N, SelectionDAG &DAG, int NumOp,
return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
}
+static SDValue customLegalizeToRotateWOp(SDNode *N, SelectionDAG &DAG,
+ unsigned ExtOpc = ISD::ANY_EXTEND) {
+ SDLoc DL(N);
+ SDValue NewOp0, NewOp1, NewRes;
+
+ NewOp0 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(0));
+ NewOp1 = DAG.getNode(ExtOpc, DL, MVT::i64, N->getOperand(1));
+
+ if (N->getOpcode() == ISD::ROTL) {
+ SDValue TmpOp = DAG.getConstant(32, DL, MVT::i64);
+ NewOp1 = DAG.getNode(ISD::SUB, DL, MVT::i64, TmpOp, NewOp1);
+ }
+
+ NewRes = DAG.getNode(LoongArchISD::ROTR_W, DL, MVT::i64, NewOp0, NewOp1);
+
+ // ReplaceNodeResults requires we maintain the same type for the return
+ // value.
+ return DAG.getNode(ISD::TRUNCATE, DL, N->getValueType(0), NewRes);
+}
+
// Helper function that emits error message for intrinsics with/without chain
// and return a UNDEF or and the chain as the results.
static void emitErrorAndReplaceIntrinsicResults(
@@ -1841,7 +1858,6 @@ void LoongArchTargetLowering::ReplaceNodeResults(
case ISD::SHL:
case ISD::SRA:
case ISD::SRL:
- case ISD::ROTR:
assert(VT == MVT::i32 && Subtarget.is64Bit() &&
"Unexpected custom legalisation");
if (N->getOperand(1).getOpcode() != ISD::Constant) {
@@ -1850,11 +1866,10 @@ void LoongArchTargetLowering::ReplaceNodeResults(
}
break;
case ISD::ROTL:
- ConstantSDNode *CN;
- if ((CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))) {
- Results.push_back(customLegalizeToWOp(N, DAG, 2));
- break;
- }
+ case ISD::ROTR:
+ assert(VT == MVT::i32 && Subtarget.is64Bit() &&
+ "Unexpected custom legalisation");
+ Results.push_back(customLegalizeToRotateWOp(N, DAG));
break;
case ISD::FP_TO_SINT: {
assert(VT == MVT::i32 && Subtarget.is64Bit() &&
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index a7f6eb9a79ebc0..a4272210d0eaa2 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -85,7 +85,6 @@ def loongarch_sll_w : SDNode<"LoongArchISD::SLL_W", SDT_LoongArchIntBinOpW>;
def loongarch_sra_w : SDNode<"LoongArchISD::SRA_W", SDT_LoongArchIntBinOpW>;
def loongarch_srl_w : SDNode<"LoongArchISD::SRL_W", SDT_LoongArchIntBinOpW>;
def loongarch_rotr_w : SDNode<"LoongArchISD::ROTR_W", SDT_LoongArchIntBinOpW>;
-def loongarch_rotl_w : SDNode<"LoongArchISD::ROTL_W", SDT_LoongArchIntBinOpW>;
def loongarch_crc_w_b_w
: SDNode<"LoongArchISD::CRC_W_B_W", SDT_LoongArchIntBinOpW, [SDNPHasChain]>;
def loongarch_crc_w_h_w
@@ -1116,12 +1115,10 @@ def : PatGprGpr<srem, MOD_D>;
def : PatGprGpr<urem, MOD_DU>;
def : PatGprGpr<rotr, ROTR_D>;
def : PatGprGpr<loongarch_rotr_w, ROTR_W>;
+def : PatGprGpr_32<rotr, ROTR_W>;
def : PatGprImm<rotr, ROTRI_D, uimm6>;
def : PatGprImm_32<rotr, ROTRI_W, uimm5>;
-def : Pat<(loongarch_rotl_w GPR:$rj, uimm5:$imm),
- (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
-def : Pat<(sext_inreg (loongarch_rotl_w GPR:$rj, uimm5:$imm), i32),
- (ROTRI_W GPR:$rj, (ImmSubFrom32 uimm5:$imm))>;
+def : PatGprImm_32<loongarch_rotr_w, ROTRI_W, uimm5>;
// TODO: Select "_W[U]" instructions for i32xi32 if only lower 32 bits of the
// product are used.
def : PatGprGpr<mul, MUL_D>;
diff --git a/llvm/test/CodeGen/LoongArch/rotl-rotr.ll b/llvm/test/CodeGen/LoongArch/rotl-rotr.ll
index 8646771e5d48a1..9552930be76ae2 100644
--- a/llvm/test/CodeGen/LoongArch/rotl-rotr.ll
+++ b/llvm/test/CodeGen/LoongArch/rotl-rotr.ll
@@ -14,10 +14,9 @@ define signext i32 @rotl_32(i32 signext %x, i32 signext %y) nounwind {
;
; LA64-LABEL: rotl_32:
; LA64: # %bb.0:
-; LA64-NEXT: sll.w $a2, $a0, $a1
-; LA64-NEXT: sub.d $a1, $zero, $a1
-; LA64-NEXT: srl.w $a0, $a0, $a1
-; LA64-NEXT: or $a0, $a2, $a0
+; LA64-NEXT: ori $a2, $zero, 32
+; LA64-NEXT: sub.d $a1, $a2, $a1
+; LA64-NEXT: rotr.w $a0, $a0, $a1
; LA64-NEXT: ret
%z = sub i32 32, %y
%b = shl i32 %x, %y
@@ -152,10 +151,9 @@ define signext i32 @rotl_32_mask(i32 signext %x, i32 signext %y) nounwind {
;
; LA64-LABEL: rotl_32_mask:
; LA64: # %bb.0:
-; LA64-NEXT: sll.w $a2, $a0, $a1
-; LA64-NEXT: sub.d $a1, $zero, $a1
-; LA64-NEXT: srl.w $a0, $a0, $a1
-; LA64-NEXT: or $a0, $a2, $a0
+; LA64-NEXT: ori $a2, $zero, 32
+; LA64-NEXT: sub.d $a1, $a2, $a1
+; LA64-NEXT: rotr.w $a0, $a0, $a1
; LA64-NEXT: ret
%z = sub i32 0, %y
%and = and i32 %z, 31
@@ -174,10 +172,9 @@ define signext i32 @rotl_32_mask_and_63_and_31(i32 signext %x, i32 signext %y) n
;
; LA64-LABEL: rotl_32_mask_and_63_and_31:
; LA64: # %bb.0:
-; LA64-NEXT: sll.w $a2, $a0, $a1
-; LA64-NEXT: sub.d $a1, $zero, $a1
-; LA64-NEXT: srl.w $a0, $a0, $a1
-; LA64-NEXT: or $a0, $a2, $a0
+; LA64-NEXT: ori $a2, $zero, 32
+; LA64-NEXT: sub.d $a1, $a2, $a1
+; LA64-NEXT: rotr.w $a0, $a0, $a1
; LA64-NEXT: ret
%a = and i32 %y, 63
%b = shl i32 %x, %a
@@ -197,10 +194,9 @@ define signext i32 @rotl_32_mask_or_64_or_32(i32 signext %x, i32 signext %y) nou
;
; LA64-LABEL: rotl_32_mask_or_64_or_32:
; LA64: # %bb.0:
-; LA64-NEXT: sll.w $a2, $a0, $a1
-; LA64-NEXT: sub.d $a1, $zero, $a1
-; LA64-NEXT: srl.w $a0, $a0, $a1
-; LA64-NEXT: or $a0, $a2, $a0
+; LA64-NEXT: ori $a2, $zero, 32
+; LA64-NEXT: sub.d $a1, $a2, $a1
+; LA64-NEXT: rotr.w $a0, $a0, $a1
; LA64-NEXT: ret
%a = or i32 %y, 64
%b = shl i32 %x, %a
@@ -591,10 +587,7 @@ define signext i32 @rotr_i32_fshr(i32 signext %a) nounwind {
;
; LA64-LABEL: rotr_i32_fshr:
; LA64: # %bb.0:
-; LA64-NEXT: slli.d $a1, $a0, 20
-; LA64-NEXT: bstrpick.d $a0, $a0, 31, 12
-; LA64-NEXT: or $a0, $a0, $a1
-; LA64-NEXT: addi.w $a0, $a0, 0
+; LA64-NEXT: rotri.w $a0, $a0, 12
; LA64-NEXT: ret
%or = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 12)
ret i32 %or
``````````
</details>
https://github.com/llvm/llvm-project/pull/91174
More information about the llvm-commits
mailing list