[llvm] 1ad84d7 - [Mips] Optimize `or (and $src1, mask), (shl $src2, shift)` to `ins` (#103017)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 12 09:06:01 PDT 2024


Author: yingopq
Date: 2024-09-13T00:05:54+08:00
New Revision: 1ad84d7961ec3ddab9233370066110ecaa5eb329

URL: https://github.com/llvm/llvm-project/commit/1ad84d7961ec3ddab9233370066110ecaa5eb329
DIFF: https://github.com/llvm/llvm-project/commit/1ad84d7961ec3ddab9233370066110ecaa5eb329.diff

LOG: [Mips] Optimize `or (and $src1, mask), (shl $src2, shift)` to `ins` (#103017)

Optimize `$dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)` to
`ins $src1, $src2, pos, size`,
where `pos = size0, size = 32 - pos`.

Fix #90325

Added: 
    llvm/test/CodeGen/Mips/ins.ll

Modified: 
    llvm/lib/Target/Mips/MipsISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index 59f78a8ca306c5..4345b8e66f6a0b 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -880,30 +880,73 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
 static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
                                 TargetLowering::DAGCombinerInfo &DCI,
                                 const MipsSubtarget &Subtarget) {
-  // Pattern match INS.
-  //  $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
-  //  where mask1 = (2**size - 1) << pos, mask0 = ~mask1
-  //  => ins $dst, $src, size, pos, $src1
   if (DCI.isBeforeLegalizeOps() || !Subtarget.hasExtractInsert())
     return SDValue();
 
-  SDValue And0 = N->getOperand(0), And1 = N->getOperand(1);
+  SDValue FirstOperand = N->getOperand(0), SecondOperand = N->getOperand(1);
   unsigned SMPos0, SMSize0, SMPos1, SMSize1;
   ConstantSDNode *CN, *CN1;
 
+  if ((FirstOperand.getOpcode() == ISD::AND &&
+       SecondOperand.getOpcode() == ISD::SHL) ||
+      (FirstOperand.getOpcode() == ISD::SHL &&
+       SecondOperand.getOpcode() == ISD::AND)) {
+    // Pattern match INS.
+    //   $dst = or (and $src1, (2**size0 - 1)), (shl $src2, size0)
+    //   ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
+    //   Or:
+    //   $dst = or (shl $src2, size0), (and $src1, (2**size0 - 1))
+    //   ==> ins $src1, $src2, pos, size, pos = size0, size = 32 - pos;
+    SDValue AndOperand0 = FirstOperand.getOpcode() == ISD::AND
+                              ? FirstOperand.getOperand(0)
+                              : SecondOperand.getOperand(0);
+    SDValue ShlOperand0 = FirstOperand.getOpcode() == ISD::AND
+                              ? SecondOperand.getOperand(0)
+                              : FirstOperand.getOperand(0);
+    SDValue AndMask = FirstOperand.getOpcode() == ISD::AND
+                          ? FirstOperand.getOperand(1)
+                          : SecondOperand.getOperand(1);
+    if (!(CN = dyn_cast<ConstantSDNode>(AndMask)) ||
+        !isShiftedMask_64(CN->getZExtValue(), SMPos0, SMSize0))
+      return SDValue();
+
+    SDValue ShlShift = FirstOperand.getOpcode() == ISD::AND
+                           ? SecondOperand.getOperand(1)
+                           : FirstOperand.getOperand(1);
+    if (!(CN = dyn_cast<ConstantSDNode>(ShlShift)))
+      return SDValue();
+    uint64_t ShlShiftValue = CN->getZExtValue();
+
+    if (SMPos0 != 0 || SMSize0 != ShlShiftValue)
+      return SDValue();
+
+    SDLoc DL(N);
+    EVT ValTy = N->getValueType(0);
+    SMPos1 = ShlShiftValue;
+    assert(SMPos1 < ValTy.getSizeInBits());
+    SMSize1 = (ValTy == MVT::i64 ? 64 : 32) - SMPos1;
+    return DAG.getNode(MipsISD::Ins, DL, ValTy, ShlOperand0,
+                       DAG.getConstant(SMPos1, DL, MVT::i32),
+                       DAG.getConstant(SMSize1, DL, MVT::i32), AndOperand0);
+  }
+
   // See if Op's first operand matches (and $src1 , mask0).
-  if (And0.getOpcode() != ISD::AND)
+  if (FirstOperand.getOpcode() != ISD::AND)
     return SDValue();
 
-  if (!(CN = dyn_cast<ConstantSDNode>(And0.getOperand(1))) ||
+  // Pattern match INS.
+  //  $dst = or (and $src1 , mask0), (and (shl $src, pos), mask1),
+  //  where mask1 = (2**size - 1) << pos, mask0 = ~mask1
+  //  => ins $dst, $src, size, pos, $src1
+  if (!(CN = dyn_cast<ConstantSDNode>(FirstOperand.getOperand(1))) ||
       !isShiftedMask_64(~CN->getSExtValue(), SMPos0, SMSize0))
     return SDValue();
 
   // See if Op's second operand matches (and (shl $src, pos), mask1).
-  if (And1.getOpcode() == ISD::AND &&
-      And1.getOperand(0).getOpcode() == ISD::SHL) {
+  if (SecondOperand.getOpcode() == ISD::AND &&
+      SecondOperand.getOperand(0).getOpcode() == ISD::SHL) {
 
-    if (!(CN = dyn_cast<ConstantSDNode>(And1.getOperand(1))) ||
+    if (!(CN = dyn_cast<ConstantSDNode>(SecondOperand.getOperand(1))) ||
         !isShiftedMask_64(CN->getZExtValue(), SMPos1, SMSize1))
       return SDValue();
 
@@ -911,7 +954,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
     if (SMPos0 != SMPos1 || SMSize0 != SMSize1)
       return SDValue();
 
-    SDValue Shl = And1.getOperand(0);
+    SDValue Shl = SecondOperand.getOperand(0);
 
     if (!(CN = dyn_cast<ConstantSDNode>(Shl.getOperand(1))))
       return SDValue();
@@ -928,7 +971,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
     return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0),
                        DAG.getConstant(SMPos0, DL, MVT::i32),
                        DAG.getConstant(SMSize0, DL, MVT::i32),
-                       And0.getOperand(0));
+                       FirstOperand.getOperand(0));
   } else {
     // Pattern match DINS.
     //  $dst = or (and $src, mask0), mask1
@@ -938,9 +981,9 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
         ((SMSize0 + SMPos0 <= 64 && Subtarget.hasMips64r2()) ||
          (SMSize0 + SMPos0 <= 32))) {
       // Check if AND instruction has constant as argument
-      bool isConstCase = And1.getOpcode() != ISD::AND;
-      if (And1.getOpcode() == ISD::AND) {
-        if (!(CN1 = dyn_cast<ConstantSDNode>(And1->getOperand(1))))
+      bool isConstCase = SecondOperand.getOpcode() != ISD::AND;
+      if (SecondOperand.getOpcode() == ISD::AND) {
+        if (!(CN1 = dyn_cast<ConstantSDNode>(SecondOperand->getOperand(1))))
           return SDValue();
       } else {
         if (!(CN1 = dyn_cast<ConstantSDNode>(N->getOperand(1))))
@@ -957,7 +1000,8 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
       SDValue SrlX;
       if (!isConstCase) {
         Const1 = DAG.getConstant(SMPos0, DL, MVT::i32);
-        SrlX = DAG.getNode(ISD::SRL, DL, And1->getValueType(0), And1, Const1);
+        SrlX = DAG.getNode(ISD::SRL, DL, SecondOperand->getValueType(0),
+                           SecondOperand, Const1);
       }
       return DAG.getNode(
           MipsISD::Ins, DL, N->getValueType(0),
@@ -968,8 +1012,7 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG,
           DAG.getConstant(ValTy.getSizeInBits() / 8 < 8 ? SMSize0 & 31
                                                         : SMSize0,
                           DL, MVT::i32),
-          And0->getOperand(0));
-
+          FirstOperand->getOperand(0));
     }
     return SDValue();
   }

diff  --git a/llvm/test/CodeGen/Mips/ins.ll b/llvm/test/CodeGen/Mips/ins.ll
new file mode 100644
index 00000000000000..615dc8f3d6ac5a
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/ins.ll
@@ -0,0 +1,60 @@
+; RUN: llc -O3 -mcpu=mips32r2 -mtriple=mipsel-linux-gnu < %s -o - \
+; RUN:   | FileCheck %s --check-prefixes=MIPS32R2
+; RUN: llc -O3 -mcpu=mips64r2 -march=mips64el  < %s \
+; RUN:   | FileCheck %s --check-prefixes=MIPS64R2
+
+define i32 @or_and_shl(i32 %a, i32 %b) {
+; MIPS32R2-LABEL: or_and_shl:
+; MIPS32R2:       # %bb.0: # %entry
+; MIPS32R2-NEXT:    ins $4, $5, 31, 1
+; MIPS32R2-NEXT:    jr $ra
+; MIPS32R2-NEXT:    move $2, $4
+
+entry:
+  %shl = shl i32 %b, 31
+  %and = and i32 %a, 2147483647
+  %or = or i32 %and, %shl
+  ret i32 %or
+}
+
+define i32 @or_shl_and(i32 %a, i32 %b) {
+; MIPS32R2-LABEL: or_shl_and:
+; MIPS32R2:       # %bb.0: # %entry
+; MIPS32R2-NEXT:    ins $4, $5, 31, 1
+; MIPS32R2-NEXT:    jr $ra
+; MIPS32R2-NEXT:    move $2, $4
+
+entry:
+  %shl = shl i32 %b, 31
+  %and = and i32 %a, 2147483647
+  %or = or i32 %shl, %and
+  ret i32 %or
+}
+
+define i64 @dinsm(i64 %a, i64 %b) {
+; MIPS64R2-LABEL: dinsm:
+; MIPS64R2:       # %bb.0: # %entry
+; MIPS64R2-NEXT:    dinsm $4, $5, 17, 47
+; MIPS64R2-NEXT:    jr $ra
+; MIPS64R2-NEXT:    move $2, $4
+
+entry:
+  %shl = shl i64 %b, 17
+  %and = and i64 %a, 131071
+  %or = or i64 %shl, %and
+  ret i64 %or
+}
+
+define i64 @dinsu(i64 %a, i64 %b) {
+; MIPS64R2-LABEL: dinsu:
+; MIPS64R2:       # %bb.0: # %entry
+; MIPS64R2-NEXT:    dinsu $4, $5, 35, 29
+; MIPS64R2-NEXT:    jr $ra
+; MIPS64R2-NEXT:    move $2, $4
+
+entry:
+  %shl = shl i64 %b, 35
+  %and = and i64 %a, 34359738367
+  %or = or i64 %shl, %and
+  ret i64 %or
+}


        


More information about the llvm-commits mailing list