[llvm] 20e6ada - [LoongArch] Combine ((x & shifted_mask) >> shamt) to bstrpick.{w/d}
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 23 02:20:41 PDT 2022
Author: Weining Lu
Date: 2022-06-23T17:10:06+08:00
New Revision: 20e6ada2fb94a97e677c5493dd6c1886d416c91a
URL: https://github.com/llvm/llvm-project/commit/20e6ada2fb94a97e677c5493dd6c1886d416c91a
DIFF: https://github.com/llvm/llvm-project/commit/20e6ada2fb94a97e677c5493dd6c1886d416c91a.diff
LOG: [LoongArch] Combine ((x & shifted_mask) >> shamt) to bstrpick.{w/d}
This is an improvement to LoongArch codegen. In D127206 we combined
((x >> shamt) & shifted_mask) to bstrpick and here we do a similar
combination when certain conditions are met.
Thanks to @xen0n for reminding me.
Differential Revision: https://reviews.llvm.org/D128191
Added:
Modified:
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/test/CodeGen/LoongArch/bstrpick_d.ll
llvm/test/CodeGen/LoongArch/bstrpick_w.ll
llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 18c46eae93167..d5a469216859c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -75,6 +75,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setMinFunctionAlignment(FunctionAlignment);
setTargetDAGCombine(ISD::AND);
+ setTargetDAGCombine(ISD::SRL);
}
SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
@@ -303,6 +304,47 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
DAG.getConstant(lsb, DL, GRLenVT));
}
+static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const LoongArchSubtarget &Subtarget) {
+ if (DCI.isBeforeLegalizeOps())
+ return SDValue();
+
+ // $dst = srl (and $src, Mask), Shamt
+ // =>
+ // BSTRPICK $dst, $src, MaskIdx+MaskLen-1, Shamt
+ // when Mask is a shifted mask, and MaskIdx <= Shamt <= MaskIdx+MaskLen-1
+ //
+
+ SDValue FirstOperand = N->getOperand(0);
+ ConstantSDNode *CN;
+ EVT ValTy = N->getValueType(0);
+ SDLoc DL(N);
+ MVT GRLenVT = Subtarget.getGRLenVT();
+ unsigned MaskIdx, MaskLen;
+ uint64_t Shamt;
+
+ // The first operand must be an AND and the second operand of the AND must be
+ // a shifted mask.
+ if (FirstOperand.getOpcode() != ISD::AND ||
+ !(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
+ !isShiftedMask_64(CN->getZExtValue(), MaskIdx, MaskLen))
+ return SDValue();
+
+ // The second operand (shift amount) must be an immediate.
+ if (!(CN = dyn_cast<ConstantSDNode>(N->getOperand(1))))
+ return SDValue();
+
+ Shamt = CN->getZExtValue();
+ if (MaskIdx <= Shamt && Shamt <= MaskIdx + MaskLen - 1)
+ return DAG.getNode(LoongArchISD::BSTRPICK, DL, ValTy,
+ FirstOperand->getOperand(0),
+ DAG.getConstant(MaskIdx + MaskLen - 1, DL, GRLenVT),
+ DAG.getConstant(Shamt, DL, GRLenVT));
+
+ return SDValue();
+}
+
SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
@@ -311,6 +353,8 @@ SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
break;
case ISD::AND:
return performANDCombine(N, DAG, DCI, Subtarget);
+ case ISD::SRL:
+ return performSRLCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
}
diff --git a/llvm/test/CodeGen/LoongArch/bstrpick_d.ll b/llvm/test/CodeGen/LoongArch/bstrpick_d.ll
index 5882123be1c87..51d4967dc3f51 100644
--- a/llvm/test/CodeGen/LoongArch/bstrpick_d.ll
+++ b/llvm/test/CodeGen/LoongArch/bstrpick_d.ll
@@ -47,3 +47,51 @@ define i64 @and4095(i64 %a) {
%and = and i64 %a, 4095
ret i64 %and
}
+
+;; (srl (and a, 0xff0), 4) => (BSTRPICK a, 11, 4)
+define i64 @and0xff0_lshr4(i64 %a) {
+; CHECK-LABEL: and0xff0_lshr4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: bstrpick.d $a0, $a0, 11, 4
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i64 %a, 4080
+ %shr = lshr i64 %and, 4
+ ret i64 %shr
+}
+
+;; (sra (and a, 0xff0), 5) can also be combined to (BSTRPICK a, 11, 5).
+;; This is because (sra (and a, 0xff0)) would be combined to (srl (and a, 0xff0), 5)
+;; firstly by DAGCombiner::SimplifyDemandedBits.
+define i64 @and4080_ashr5(i64 %a) {
+; CHECK-LABEL: and4080_ashr5:
+; CHECK: # %bb.0:
+; CHECK-NEXT: bstrpick.d $a0, $a0, 11, 5
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i64 %a, 4080
+ %shr = ashr i64 %and, 5
+ ret i64 %shr
+}
+
+;; Negative test: the second operand of AND is not a shifted mask
+define i64 @and0xf30_lshr4(i64 %a) {
+; CHECK-LABEL: and0xf30_lshr4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: andi $a0, $a0, 3888
+; CHECK-NEXT: srli.d $a0, $a0, 4
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i64 %a, 3888
+ %shr = lshr i64 %and, 4
+ ret i64 %shr
+}
+
+;; Negative test: Shamt < MaskIdx
+define i64 @and0xff0_lshr3(i64 %a) {
+; CHECK-LABEL: and0xff0_lshr3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: andi $a0, $a0, 4080
+; CHECK-NEXT: srli.d $a0, $a0, 3
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i64 %a, 4080
+ %shr = lshr i64 %and, 3
+ ret i64 %shr
+}
diff --git a/llvm/test/CodeGen/LoongArch/bstrpick_w.ll b/llvm/test/CodeGen/LoongArch/bstrpick_w.ll
index ae71fb380e273..3475490d5eb1e 100644
--- a/llvm/test/CodeGen/LoongArch/bstrpick_w.ll
+++ b/llvm/test/CodeGen/LoongArch/bstrpick_w.ll
@@ -47,3 +47,51 @@ define i32 @and4095(i32 %a) {
%and = and i32 %a, 4095
ret i32 %and
}
+
+;; (srl (and a, 0xff0), 4) => (BSTRPICK a, 11, 4)
+define i32 @and0xff0_lshr4(i32 %a) {
+; CHECK-LABEL: and0xff0_lshr4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: bstrpick.w $a0, $a0, 11, 4
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i32 %a, 4080
+ %shr = lshr i32 %and, 4
+ ret i32 %shr
+}
+
+;; (sra (and a, 0xff0), 5) can also be combined to (BSTRPICK a, 11, 5).
+;; This is because (sra (and a, 0xff0)) would be combined to (srl (and a, 0xff0), 5)
+;; firstly by DAGCombiner::SimplifyDemandedBits.
+define i32 @and4080_ashr5(i32 %a) {
+; CHECK-LABEL: and4080_ashr5:
+; CHECK: # %bb.0:
+; CHECK-NEXT: bstrpick.w $a0, $a0, 11, 5
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i32 %a, 4080
+ %shr = ashr i32 %and, 5
+ ret i32 %shr
+}
+
+;; Negative test: the second operand of AND is not a shifted mask
+define i32 @and0xf30_lshr4(i32 %a) {
+; CHECK-LABEL: and0xf30_lshr4:
+; CHECK: # %bb.0:
+; CHECK-NEXT: andi $a0, $a0, 3888
+; CHECK-NEXT: srli.w $a0, $a0, 4
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i32 %a, 3888
+ %shr = lshr i32 %and, 4
+ ret i32 %shr
+}
+
+;; Negative test: Shamt < MaskIdx
+define i32 @and0xff0_lshr3(i32 %a) {
+; CHECK-LABEL: and0xff0_lshr3:
+; CHECK: # %bb.0:
+; CHECK-NEXT: andi $a0, $a0, 4080
+; CHECK-NEXT: srli.w $a0, $a0, 3
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %and = and i32 %a, 4080
+ %shr = lshr i32 %and, 3
+ ret i32 %shr
+}
diff --git a/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll b/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll
index fae995719dffc..2f63c64de8184 100644
--- a/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll
+++ b/llvm/test/CodeGen/LoongArch/ir-instruction/lshr.ll
@@ -103,14 +103,12 @@ define i1 @lshr_i1_3(i1 %x) {
define i8 @lshr_i8_3(i8 %x) {
; LA32-LABEL: lshr_i8_3:
; LA32: # %bb.0:
-; LA32-NEXT: andi $a0, $a0, 248
-; LA32-NEXT: srli.w $a0, $a0, 3
+; LA32-NEXT: bstrpick.w $a0, $a0, 7, 3
; LA32-NEXT: jirl $zero, $ra, 0
;
; LA64-LABEL: lshr_i8_3:
; LA64: # %bb.0:
-; LA64-NEXT: andi $a0, $a0, 248
-; LA64-NEXT: srli.d $a0, $a0, 3
+; LA64-NEXT: bstrpick.d $a0, $a0, 7, 3
; LA64-NEXT: jirl $zero, $ra, 0
%lshr = lshr i8 %x, 3
ret i8 %lshr
@@ -119,18 +117,12 @@ define i8 @lshr_i8_3(i8 %x) {
define i16 @lshr_i16_3(i16 %x) {
; LA32-LABEL: lshr_i16_3:
; LA32: # %bb.0:
-; LA32-NEXT: lu12i.w $a1, 15
-; LA32-NEXT: ori $a1, $a1, 4088
-; LA32-NEXT: and $a0, $a0, $a1
-; LA32-NEXT: srli.w $a0, $a0, 3
+; LA32-NEXT: bstrpick.w $a0, $a0, 15, 3
; LA32-NEXT: jirl $zero, $ra, 0
;
; LA64-LABEL: lshr_i16_3:
; LA64: # %bb.0:
-; LA64-NEXT: lu12i.w $a1, 15
-; LA64-NEXT: ori $a1, $a1, 4088
-; LA64-NEXT: and $a0, $a0, $a1
-; LA64-NEXT: srli.d $a0, $a0, 3
+; LA64-NEXT: bstrpick.d $a0, $a0, 15, 3
; LA64-NEXT: jirl $zero, $ra, 0
%lshr = lshr i16 %x, 3
ret i16 %lshr
@@ -144,10 +136,7 @@ define i32 @lshr_i32_3(i32 %x) {
;
; LA64-LABEL: lshr_i32_3:
; LA64: # %bb.0:
-; LA64-NEXT: addi.w $a1, $zero, -8
-; LA64-NEXT: lu32i.d $a1, 0
-; LA64-NEXT: and $a0, $a0, $a1
-; LA64-NEXT: srli.d $a0, $a0, 3
+; LA64-NEXT: bstrpick.d $a0, $a0, 31, 3
; LA64-NEXT: jirl $zero, $ra, 0
%lshr = lshr i32 %x, 3
ret i32 %lshr
More information about the llvm-commits
mailing list