[llvm] [Mips] Optimize (shift x (and y, BitWidth - 1)) to (shift x, y) (PR #73889)

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 29 18:53:49 PST 2023


https://github.com/yingopq updated https://github.com/llvm/llvm-project/pull/73889

>From ed0825367aa4e76fd4722d10a274f0ef8d454b0f Mon Sep 17 00:00:00 2001
From: Ying Huang <ying.huang at oss.cipunited.com>
Date: Fri, 24 Nov 2023 10:42:05 +0800
Subject: [PATCH] [Mips] Optimize (shift x (and y, BitWidth - 1)) to (shift x,
 y)

Do optimization to turn x >> (shift & 31/63) into a single srlv
instead of andi + srlv, since the mips variable shift instruction
already implicitly masks the shift, like x86, wasm and AMDGPU.
Copy the X86DAGToDAGISel::isUnneededShiftMask() function to MIPS
for checking whether need combine two instructions to one.
---
 llvm/lib/Target/Mips/Mips64InstrInfo.td       |  12 +-
 llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp     |  18 +++
 llvm/lib/Target/Mips/MipsISelDAGToDAG.h       |   2 +
 llvm/lib/Target/Mips/MipsInstrCompiler.td     |  33 +++++
 llvm/lib/Target/Mips/MipsInstrInfo.td         |  13 +-
 llvm/test/CodeGen/Mips/funnel-shift-rot.ll    | 120 +++++++-----------
 llvm/test/CodeGen/Mips/funnel-shift.ll        | 103 +++++++--------
 llvm/test/CodeGen/Mips/llvm-ir/ashr.ll        |  52 +++-----
 llvm/test/CodeGen/Mips/llvm-ir/lshr.ll        |   4 -
 llvm/test/CodeGen/Mips/llvm-ir/shl.ll         |  58 +++------
 .../test/CodeGen/Mips/optimizeAndPlusShift.ll |  84 ++++++++++++
 11 files changed, 276 insertions(+), 223 deletions(-)
 create mode 100644 llvm/lib/Target/Mips/MipsInstrCompiler.td
 create mode 100644 llvm/test/CodeGen/Mips/optimizeAndPlusShift.ll

diff --git a/llvm/lib/Target/Mips/Mips64InstrInfo.td b/llvm/lib/Target/Mips/Mips64InstrInfo.td
index ac679c4c01bc7cb..c0e7eef8dd9d52d 100644
--- a/llvm/lib/Target/Mips/Mips64InstrInfo.td
+++ b/llvm/lib/Target/Mips/Mips64InstrInfo.td
@@ -164,20 +164,20 @@ def NOR64  : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>, GPR_64;
 
 /// Shift Instructions
 let AdditionalPredicates = [NotInMicroMips] in {
-  def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl,
+  def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, mshl_64,
                               immZExt6>,
              SRA_FM<0x38, 0>, ISA_MIPS3;
-  def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl,
+  def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, msrl_64,
                               immZExt6>,
              SRA_FM<0x3a, 0>, ISA_MIPS3;
-  def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra,
+  def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, msra_64,
                               immZExt6>,
              SRA_FM<0x3b, 0>, ISA_MIPS3;
-  def DSLLV  : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
+  def DSLLV  : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, mshl_64>,
                SRLV_FM<0x14, 0>, ISA_MIPS3;
-  def DSRAV  : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
+  def DSRAV  : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, msra_64>,
                SRLV_FM<0x17, 0>, ISA_MIPS3;
-  def DSRLV  : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
+  def DSRLV  : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, msrl_64>,
                SRLV_FM<0x16, 0>, ISA_MIPS3;
   def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>,
                SRA_FM<0x3c, 0>, ISA_MIPS3;
diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 77ce8ba890a814c..0dc83478b133127 100644
--- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -22,6 +22,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAG.h"
 #include "llvm/CodeGen/SelectionDAGNodes.h"
 #include "llvm/CodeGen/StackProtector.h"
 #include "llvm/IR/CFG.h"
@@ -32,6 +33,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/KnownBits.h"
 #include "llvm/Target/TargetMachine.h"
 using namespace llvm;
 
@@ -324,6 +326,22 @@ bool MipsDAGToDAGISel::SelectInlineAsmMemoryOperand(
   return true;
 }
 
+bool MipsDAGToDAGISel::isUnneededShiftMask(SDNode *N,
+                                             unsigned ShAmtBits) const {
+  assert(N->getOpcode() == ISD::AND && "Unexpected opcode");
+
+  const APInt &RHS = cast<ConstantSDNode>(N->getOperand(1))->getAPIntValue();
+  if (RHS.countr_one() >= ShAmtBits) {
+    LLVM_DEBUG(dbgs() << DEBUG_TYPE <<
+	      " Need optimize 'and & shl/srl/sra' and operand value bits is "
+	      << RHS.countr_one() << "\n");
+    return true;
+  }
+
+  KnownBits Known = CurDAG->computeKnownBits(N->getOperand(0));
+  return (Known.Zero | RHS).countr_one() >= ShAmtBits;
+}
+
 char MipsDAGToDAGISel::ID = 0;
 
 INITIALIZE_PASS(MipsDAGToDAGISel, DEBUG_TYPE, PASS_NAME, false, false)
diff --git a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
index e41cb08712ca2d3..7136f691d224da7 100644
--- a/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
+++ b/llvm/lib/Target/Mips/MipsISelDAGToDAG.h
@@ -143,6 +143,8 @@ class MipsDAGToDAGISel : public SelectionDAGISel {
   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
                                     InlineAsm::ConstraintCode ConstraintID,
                                     std::vector<SDValue> &OutOps) override;
+  bool isUnneededShiftMask(SDNode *N, unsigned ShAmtBits) const;
+
 };
 }
 
diff --git a/llvm/lib/Target/Mips/MipsInstrCompiler.td b/llvm/lib/Target/Mips/MipsInstrCompiler.td
new file mode 100644
index 000000000000000..8ae3d71978b1198
--- /dev/null
+++ b/llvm/lib/Target/Mips/MipsInstrCompiler.td
@@ -0,0 +1,33 @@
+//===- MipsInstrCompiler.td - Compiler Pseudos and Patterns -*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the various pseudo instructions used by the compiler,
+// as well as Pat patterns used during instruction selection.
+//
+//===----------------------------------------------------------------------===//
+
+
+def shiftMask_32 : PatFrag<(ops node:$lhs), (and node:$lhs, imm), [{
+  return isUnneededShiftMask(N, 5);
+}]>;
+
+def shiftMask_64 : PatFrag<(ops node:$src0), (and node:$src0, imm), [{
+  return isUnneededShiftMask(N, 6);
+}]>;
+
+foreach width = [32, 64] in {
+defvar shiftMask = !cast<SDPatternOperator>("shiftMask_"#width);
+def mshl_#width : PatFrags<(ops node:$src0, node:$src1),
+  [(shl node:$src0, node:$src1), (shl node:$src0, (shiftMask node:$src1))]>;
+
+def msrl_#width : PatFrags<(ops node:$src0, node:$src1),
+  [(srl node:$src0, node:$src1), (srl node:$src0, (shiftMask node:$src1))]>;
+
+def msra_#width : PatFrags<(ops node:$src0, node:$src1),
+  [(sra node:$src0, node:$src1), (sra node:$src0, (shiftMask node:$src1))]>;
+}
diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td
index 75270857ea1352f..4b6f4b22e71b1a0 100644
--- a/llvm/lib/Target/Mips/MipsInstrInfo.td
+++ b/llvm/lib/Target/Mips/MipsInstrInfo.td
@@ -14,6 +14,7 @@
 //===----------------------------------------------------------------------===//
 // Mips profiles and nodes
 //===----------------------------------------------------------------------===//
+include "MipsInstrCompiler.td"
 
 def SDT_MipsJmpLink      : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
 def SDT_MipsCMov         : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
@@ -2079,17 +2080,17 @@ let AdditionalPredicates = [NotInMicroMips] in {
 
 let AdditionalPredicates = [NotInMicroMips] in {
   /// Shift Instructions
-  def SLL  : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl,
+  def SLL  : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, mshl_32,
                                      immZExt5>, SRA_FM<0, 0>, ISA_MIPS1;
-  def SRL  : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl,
+  def SRL  : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, msrl_32,
                                      immZExt5>, SRA_FM<2, 0>, ISA_MIPS1;
-  def SRA  : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra,
+  def SRA  : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, msra_32,
                                      immZExt5>, SRA_FM<3, 0>, ISA_MIPS1;
-  def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>,
+  def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, mshl_32>,
              SRLV_FM<4, 0>, ISA_MIPS1;
-  def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>,
+  def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, msrl_32>,
              SRLV_FM<6, 0>, ISA_MIPS1;
-  def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>,
+  def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, msra_32>,
              SRLV_FM<7, 0>, ISA_MIPS1;
 
   // Rotate Instructions
diff --git a/llvm/test/CodeGen/Mips/funnel-shift-rot.ll b/llvm/test/CodeGen/Mips/funnel-shift-rot.ll
index e17980e98e9b55b..ee187678949e95f 100644
--- a/llvm/test/CodeGen/Mips/funnel-shift-rot.ll
+++ b/llvm/test/CodeGen/Mips/funnel-shift-rot.ll
@@ -62,10 +62,8 @@ define i16 @rotl_i16(i16 %x, i16 %z) {
 define i32 @rotl_i32(i32 %x, i32 %z) {
 ; CHECK-LABEL: rotl_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi $1, $5, 31
-; CHECK-NEXT:    sllv $1, $4, $1
+; CHECK-NEXT:    sllv $1, $4, $5
 ; CHECK-NEXT:    negu $2, $5
-; CHECK-NEXT:    andi $2, $2, 31
 ; CHECK-NEXT:    srlv $2, $4, $2
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    or $2, $1, $2
@@ -80,15 +78,13 @@ define i64 @rotl_i64(i64 %x, i64 %z) {
 ; CHECK-BE-NEXT:    andi $1, $1, 1
 ; CHECK-BE-NEXT:    move $3, $4
 ; CHECK-BE-NEXT:    movn $3, $5, $1
-; CHECK-BE-NEXT:    andi $6, $7, 31
-; CHECK-BE-NEXT:    sllv $2, $3, $6
+; CHECK-BE-NEXT:    sllv $2, $3, $7
 ; CHECK-BE-NEXT:    movn $5, $4, $1
 ; CHECK-BE-NEXT:    srl $1, $5, 1
 ; CHECK-BE-NEXT:    not $4, $7
-; CHECK-BE-NEXT:    andi $4, $4, 31
 ; CHECK-BE-NEXT:    srlv $1, $1, $4
 ; CHECK-BE-NEXT:    or $2, $2, $1
-; CHECK-BE-NEXT:    sllv $1, $5, $6
+; CHECK-BE-NEXT:    sllv $1, $5, $7
 ; CHECK-BE-NEXT:    srl $3, $3, 1
 ; CHECK-BE-NEXT:    srlv $3, $3, $4
 ; CHECK-BE-NEXT:    jr $ra
@@ -100,15 +96,13 @@ define i64 @rotl_i64(i64 %x, i64 %z) {
 ; CHECK-LE-NEXT:    andi $1, $1, 1
 ; CHECK-LE-NEXT:    move $3, $4
 ; CHECK-LE-NEXT:    movn $3, $5, $1
-; CHECK-LE-NEXT:    andi $7, $6, 31
-; CHECK-LE-NEXT:    sllv $2, $3, $7
+; CHECK-LE-NEXT:    sllv $2, $3, $6
 ; CHECK-LE-NEXT:    movn $5, $4, $1
 ; CHECK-LE-NEXT:    srl $1, $5, 1
 ; CHECK-LE-NEXT:    not $4, $6
-; CHECK-LE-NEXT:    andi $4, $4, 31
 ; CHECK-LE-NEXT:    srlv $1, $1, $4
 ; CHECK-LE-NEXT:    or $2, $2, $1
-; CHECK-LE-NEXT:    sllv $1, $5, $7
+; CHECK-LE-NEXT:    sllv $1, $5, $6
 ; CHECK-LE-NEXT:    srl $3, $3, 1
 ; CHECK-LE-NEXT:    srlv $3, $3, $4
 ; CHECK-LE-NEXT:    jr $ra
@@ -122,35 +116,27 @@ define i64 @rotl_i64(i64 %x, i64 %z) {
 define <4 x i32> @rotl_v4i32(<4 x i32> %x, <4 x i32> %z) {
 ; CHECK-LABEL: rotl_v4i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    lw $1, 24($sp)
+; CHECK-NEXT:    lw $1, 20($sp)
 ; CHECK-NEXT:    negu $2, $1
-; CHECK-NEXT:    lw $3, 20($sp)
+; CHECK-NEXT:    lw $3, 24($sp)
 ; CHECK-NEXT:    negu $8, $3
-; CHECK-NEXT:    andi $8, $8, 31
-; CHECK-NEXT:    andi $2, $2, 31
-; CHECK-NEXT:    andi $3, $3, 31
-; CHECK-NEXT:    andi $1, $1, 31
-; CHECK-NEXT:    lw $9, 16($sp)
-; CHECK-NEXT:    sllv $1, $6, $1
-; CHECK-NEXT:    srlv $6, $6, $2
-; CHECK-NEXT:    sllv $3, $5, $3
-; CHECK-NEXT:    srlv $5, $5, $8
-; CHECK-NEXT:    andi $2, $9, 31
-; CHECK-NEXT:    sllv $2, $4, $2
-; CHECK-NEXT:    negu $8, $9
-; CHECK-NEXT:    andi $8, $8, 31
-; CHECK-NEXT:    srlv $4, $4, $8
-; CHECK-NEXT:    lw $8, 28($sp)
-; CHECK-NEXT:    or $2, $2, $4
-; CHECK-NEXT:    or $3, $3, $5
-; CHECK-NEXT:    or $4, $1, $6
-; CHECK-NEXT:    andi $1, $8, 31
-; CHECK-NEXT:    sllv $1, $7, $1
-; CHECK-NEXT:    negu $5, $8
-; CHECK-NEXT:    andi $5, $5, 31
-; CHECK-NEXT:    srlv $5, $7, $5
+; CHECK-NEXT:    sllv $9, $6, $3
+; CHECK-NEXT:    srlv $6, $6, $8
+; CHECK-NEXT:    sllv $1, $5, $1
+; CHECK-NEXT:    srlv $3, $5, $2
+; CHECK-NEXT:    lw $2, 16($sp)
+; CHECK-NEXT:    sllv $5, $4, $2
+; CHECK-NEXT:    negu $2, $2
+; CHECK-NEXT:    srlv $2, $4, $2
+; CHECK-NEXT:    or $2, $5, $2
+; CHECK-NEXT:    or $3, $1, $3
+; CHECK-NEXT:    or $4, $9, $6
+; CHECK-NEXT:    lw $1, 28($sp)
+; CHECK-NEXT:    sllv $5, $7, $1
+; CHECK-NEXT:    negu $1, $1
+; CHECK-NEXT:    srlv $1, $7, $1
 ; CHECK-NEXT:    jr $ra
-; CHECK-NEXT:    or $5, $1, $5
+; CHECK-NEXT:    or $5, $5, $1
   %f = call <4 x i32> @llvm.fshl.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
   ret <4 x i32> %f
 }
@@ -224,10 +210,8 @@ define i16 @rotr_i16(i16 %x, i16 %z) {
 define i32 @rotr_i32(i32 %x, i32 %z) {
 ; CHECK-LABEL: rotr_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi $1, $5, 31
-; CHECK-NEXT:    srlv $1, $4, $1
+; CHECK-NEXT:    srlv $1, $4, $5
 ; CHECK-NEXT:    negu $2, $5
-; CHECK-NEXT:    andi $2, $2, 31
 ; CHECK-NEXT:    sllv $2, $4, $2
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    or $2, $1, $2
@@ -241,15 +225,13 @@ define i64 @rotr_i64(i64 %x, i64 %z) {
 ; CHECK-BE-NEXT:    andi $1, $7, 32
 ; CHECK-BE-NEXT:    move $3, $5
 ; CHECK-BE-NEXT:    movz $3, $4, $1
-; CHECK-BE-NEXT:    andi $6, $7, 31
-; CHECK-BE-NEXT:    srlv $2, $3, $6
+; CHECK-BE-NEXT:    srlv $2, $3, $7
 ; CHECK-BE-NEXT:    movz $4, $5, $1
 ; CHECK-BE-NEXT:    sll $1, $4, 1
 ; CHECK-BE-NEXT:    not $5, $7
-; CHECK-BE-NEXT:    andi $5, $5, 31
 ; CHECK-BE-NEXT:    sllv $1, $1, $5
 ; CHECK-BE-NEXT:    or $2, $1, $2
-; CHECK-BE-NEXT:    srlv $1, $4, $6
+; CHECK-BE-NEXT:    srlv $1, $4, $7
 ; CHECK-BE-NEXT:    sll $3, $3, 1
 ; CHECK-BE-NEXT:    sllv $3, $3, $5
 ; CHECK-BE-NEXT:    jr $ra
@@ -260,15 +242,13 @@ define i64 @rotr_i64(i64 %x, i64 %z) {
 ; CHECK-LE-NEXT:    andi $1, $6, 32
 ; CHECK-LE-NEXT:    move $3, $5
 ; CHECK-LE-NEXT:    movz $3, $4, $1
-; CHECK-LE-NEXT:    andi $7, $6, 31
-; CHECK-LE-NEXT:    srlv $2, $3, $7
+; CHECK-LE-NEXT:    srlv $2, $3, $6
 ; CHECK-LE-NEXT:    movz $4, $5, $1
 ; CHECK-LE-NEXT:    sll $1, $4, 1
 ; CHECK-LE-NEXT:    not $5, $6
-; CHECK-LE-NEXT:    andi $5, $5, 31
 ; CHECK-LE-NEXT:    sllv $1, $1, $5
 ; CHECK-LE-NEXT:    or $2, $1, $2
-; CHECK-LE-NEXT:    srlv $1, $4, $7
+; CHECK-LE-NEXT:    srlv $1, $4, $6
 ; CHECK-LE-NEXT:    sll $3, $3, 1
 ; CHECK-LE-NEXT:    sllv $3, $3, $5
 ; CHECK-LE-NEXT:    jr $ra
@@ -282,35 +262,27 @@ define i64 @rotr_i64(i64 %x, i64 %z) {
 define <4 x i32> @rotr_v4i32(<4 x i32> %x, <4 x i32> %z) {
 ; CHECK-LABEL: rotr_v4i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    lw $1, 24($sp)
+; CHECK-NEXT:    lw $1, 20($sp)
 ; CHECK-NEXT:    negu $2, $1
-; CHECK-NEXT:    lw $3, 20($sp)
+; CHECK-NEXT:    lw $3, 24($sp)
 ; CHECK-NEXT:    negu $8, $3
-; CHECK-NEXT:    andi $8, $8, 31
-; CHECK-NEXT:    andi $2, $2, 31
-; CHECK-NEXT:    andi $3, $3, 31
-; CHECK-NEXT:    andi $1, $1, 31
-; CHECK-NEXT:    lw $9, 16($sp)
-; CHECK-NEXT:    srlv $1, $6, $1
-; CHECK-NEXT:    sllv $6, $6, $2
-; CHECK-NEXT:    srlv $3, $5, $3
-; CHECK-NEXT:    sllv $5, $5, $8
-; CHECK-NEXT:    andi $2, $9, 31
-; CHECK-NEXT:    srlv $2, $4, $2
-; CHECK-NEXT:    negu $8, $9
-; CHECK-NEXT:    andi $8, $8, 31
-; CHECK-NEXT:    sllv $4, $4, $8
-; CHECK-NEXT:    lw $8, 28($sp)
-; CHECK-NEXT:    or $2, $2, $4
-; CHECK-NEXT:    or $3, $3, $5
-; CHECK-NEXT:    or $4, $1, $6
-; CHECK-NEXT:    andi $1, $8, 31
-; CHECK-NEXT:    srlv $1, $7, $1
-; CHECK-NEXT:    negu $5, $8
-; CHECK-NEXT:    andi $5, $5, 31
-; CHECK-NEXT:    sllv $5, $7, $5
+; CHECK-NEXT:    srlv $9, $6, $3
+; CHECK-NEXT:    sllv $6, $6, $8
+; CHECK-NEXT:    srlv $1, $5, $1
+; CHECK-NEXT:    sllv $3, $5, $2
+; CHECK-NEXT:    lw $2, 16($sp)
+; CHECK-NEXT:    srlv $5, $4, $2
+; CHECK-NEXT:    negu $2, $2
+; CHECK-NEXT:    sllv $2, $4, $2
+; CHECK-NEXT:    or $2, $5, $2
+; CHECK-NEXT:    or $3, $1, $3
+; CHECK-NEXT:    or $4, $9, $6
+; CHECK-NEXT:    lw $1, 28($sp)
+; CHECK-NEXT:    srlv $5, $7, $1
+; CHECK-NEXT:    negu $1, $1
+; CHECK-NEXT:    sllv $1, $7, $1
 ; CHECK-NEXT:    jr $ra
-; CHECK-NEXT:    or $5, $1, $5
+; CHECK-NEXT:    or $5, $5, $1
   %f = call <4 x i32> @llvm.fshr.v4i32(<4 x i32> %x, <4 x i32> %x, <4 x i32> %z)
   ret <4 x i32> %f
 }
diff --git a/llvm/test/CodeGen/Mips/funnel-shift.ll b/llvm/test/CodeGen/Mips/funnel-shift.ll
index 737e95c8262a394..bda2b477b52f305 100644
--- a/llvm/test/CodeGen/Mips/funnel-shift.ll
+++ b/llvm/test/CodeGen/Mips/funnel-shift.ll
@@ -33,12 +33,10 @@ define i16 @fshl_i16(i16 %x, i16 %y, i16 %z) {
 define i32 @fshl_i32(i32 %x, i32 %y, i32 %z) {
 ; CHECK-LABEL: fshl_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi $1, $6, 31
-; CHECK-NEXT:    sllv $1, $4, $1
-; CHECK-NEXT:    srl $2, $5, 1
-; CHECK-NEXT:    not $3, $6
-; CHECK-NEXT:    andi $3, $3, 31
-; CHECK-NEXT:    srlv $2, $2, $3
+; CHECK-NEXT:    sllv $1, $4, $6
+; CHECK-NEXT:    not $2, $6
+; CHECK-NEXT:    srl $3, $5, 1
+; CHECK-NEXT:    srlv $2, $3, $2
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    or $2, $1, $2
   %f = call i32 @llvm.fshl.i32(i32 %x, i32 %y, i32 %z)
@@ -72,25 +70,23 @@ define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
 ; CHECK-BE-NEXT:    addiu $6, $zero, 0
 ; CHECK-BE-NEXT:    jal __umoddi3
 ; CHECK-BE-NEXT:    addiu $7, $zero, 37
-; CHECK-BE-NEXT:    not $1, $3
-; CHECK-BE-NEXT:    srl $2, $3, 5
-; CHECK-BE-NEXT:    andi $4, $2, 1
-; CHECK-BE-NEXT:    movn $19, $18, $4
-; CHECK-BE-NEXT:    andi $3, $3, 31
+; CHECK-BE-NEXT:    srl $1, $3, 5
+; CHECK-BE-NEXT:    andi $1, $1, 1
+; CHECK-BE-NEXT:    movn $19, $18, $1
 ; CHECK-BE-NEXT:    sllv $2, $19, $3
-; CHECK-BE-NEXT:    andi $1, $1, 31
+; CHECK-BE-NEXT:    not $4, $3
 ; CHECK-BE-NEXT:    srl $5, $16, 5
 ; CHECK-BE-NEXT:    sll $6, $17, 27
 ; CHECK-BE-NEXT:    or $5, $6, $5
-; CHECK-BE-NEXT:    movn $18, $5, $4
+; CHECK-BE-NEXT:    movn $18, $5, $1
 ; CHECK-BE-NEXT:    srl $6, $18, 1
-; CHECK-BE-NEXT:    srlv $6, $6, $1
+; CHECK-BE-NEXT:    srlv $6, $6, $4
 ; CHECK-BE-NEXT:    or $2, $2, $6
 ; CHECK-BE-NEXT:    sllv $3, $18, $3
 ; CHECK-BE-NEXT:    sll $6, $16, 27
-; CHECK-BE-NEXT:    movn $5, $6, $4
-; CHECK-BE-NEXT:    srl $4, $5, 1
-; CHECK-BE-NEXT:    srlv $1, $4, $1
+; CHECK-BE-NEXT:    movn $5, $6, $1
+; CHECK-BE-NEXT:    srl $1, $5, 1
+; CHECK-BE-NEXT:    srlv $1, $1, $4
 ; CHECK-BE-NEXT:    or $3, $3, $1
 ; CHECK-BE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
 ; CHECK-BE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
@@ -125,26 +121,25 @@ define i37 @fshl_i37(i37 %x, i37 %y, i37 %z) {
 ; CHECK-LE-NEXT:    jal __umoddi3
 ; CHECK-LE-NEXT:    addiu $7, $zero, 0
 ; CHECK-LE-NEXT:    srl $1, $2, 5
-; CHECK-LE-NEXT:    andi $1, $1, 1
-; CHECK-LE-NEXT:    srl $3, $17, 5
+; CHECK-LE-NEXT:    andi $3, $1, 1
+; CHECK-LE-NEXT:    srl $1, $17, 5
 ; CHECK-LE-NEXT:    sll $4, $16, 27
-; CHECK-LE-NEXT:    or $3, $4, $3
+; CHECK-LE-NEXT:    or $1, $4, $1
 ; CHECK-LE-NEXT:    move $4, $19
-; CHECK-LE-NEXT:    movn $4, $3, $1
-; CHECK-LE-NEXT:    andi $5, $2, 31
-; CHECK-LE-NEXT:    sllv $6, $4, $5
-; CHECK-LE-NEXT:    not $2, $2
-; CHECK-LE-NEXT:    andi $7, $2, 31
-; CHECK-LE-NEXT:    sll $2, $17, 27
-; CHECK-LE-NEXT:    movn $3, $2, $1
-; CHECK-LE-NEXT:    srl $2, $3, 1
-; CHECK-LE-NEXT:    srlv $2, $2, $7
-; CHECK-LE-NEXT:    or $2, $6, $2
-; CHECK-LE-NEXT:    movn $18, $19, $1
-; CHECK-LE-NEXT:    sllv $1, $18, $5
+; CHECK-LE-NEXT:    movn $4, $1, $3
+; CHECK-LE-NEXT:    sllv $5, $4, $2
+; CHECK-LE-NEXT:    not $6, $2
+; CHECK-LE-NEXT:    sll $7, $17, 27
+; CHECK-LE-NEXT:    movn $1, $7, $3
+; CHECK-LE-NEXT:    srl $1, $1, 1
+; CHECK-LE-NEXT:    srlv $1, $1, $6
+; CHECK-LE-NEXT:    or $1, $5, $1
+; CHECK-LE-NEXT:    movn $18, $19, $3
+; CHECK-LE-NEXT:    sllv $2, $18, $2
 ; CHECK-LE-NEXT:    srl $3, $4, 1
-; CHECK-LE-NEXT:    srlv $3, $3, $7
-; CHECK-LE-NEXT:    or $3, $1, $3
+; CHECK-LE-NEXT:    srlv $3, $3, $6
+; CHECK-LE-NEXT:    or $3, $2, $3
+; CHECK-LE-NEXT:    move $2, $1
 ; CHECK-LE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
 ; CHECK-LE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
 ; CHECK-LE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
@@ -278,12 +273,10 @@ define i16 @fshr_i16(i16 %x, i16 %y, i16 %z) {
 define i32 @fshr_i32(i32 %x, i32 %y, i32 %z) {
 ; CHECK-LABEL: fshr_i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    andi $1, $6, 31
-; CHECK-NEXT:    srlv $1, $5, $1
-; CHECK-NEXT:    sll $2, $4, 1
-; CHECK-NEXT:    not $3, $6
-; CHECK-NEXT:    andi $3, $3, 31
-; CHECK-NEXT:    sllv $2, $2, $3
+; CHECK-NEXT:    srlv $1, $5, $6
+; CHECK-NEXT:    not $2, $6
+; CHECK-NEXT:    sll $3, $4, 1
+; CHECK-NEXT:    sllv $2, $3, $2
 ; CHECK-NEXT:    jr $ra
 ; CHECK-NEXT:    or $2, $2, $1
   %f = call i32 @llvm.fshr.i32(i32 %x, i32 %y, i32 %z)
@@ -324,19 +317,17 @@ define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
 ; CHECK-BE-NEXT:    or $4, $4, $2
 ; CHECK-BE-NEXT:    movz $19, $18, $3
 ; CHECK-BE-NEXT:    movz $18, $4, $3
-; CHECK-BE-NEXT:    andi $5, $1, 31
-; CHECK-BE-NEXT:    srlv $2, $18, $5
-; CHECK-BE-NEXT:    not $1, $1
-; CHECK-BE-NEXT:    andi $1, $1, 31
+; CHECK-BE-NEXT:    srlv $2, $18, $1
+; CHECK-BE-NEXT:    not $5, $1
 ; CHECK-BE-NEXT:    sll $6, $19, 1
-; CHECK-BE-NEXT:    sllv $6, $6, $1
+; CHECK-BE-NEXT:    sllv $6, $6, $5
 ; CHECK-BE-NEXT:    sll $7, $16, 27
 ; CHECK-BE-NEXT:    or $2, $6, $2
 ; CHECK-BE-NEXT:    movz $4, $7, $3
-; CHECK-BE-NEXT:    srlv $3, $4, $5
-; CHECK-BE-NEXT:    sll $4, $18, 1
-; CHECK-BE-NEXT:    sllv $1, $4, $1
-; CHECK-BE-NEXT:    or $3, $1, $3
+; CHECK-BE-NEXT:    srlv $1, $4, $1
+; CHECK-BE-NEXT:    sll $3, $18, 1
+; CHECK-BE-NEXT:    sllv $3, $3, $5
+; CHECK-BE-NEXT:    or $3, $3, $1
 ; CHECK-BE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
 ; CHECK-BE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
 ; CHECK-BE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
@@ -378,18 +369,16 @@ define i37 @fshr_i37(i37 %x, i37 %y, i37 %z) {
 ; CHECK-LE-NEXT:    move $5, $19
 ; CHECK-LE-NEXT:    movz $5, $2, $3
 ; CHECK-LE-NEXT:    movz $2, $4, $3
-; CHECK-LE-NEXT:    andi $4, $1, 31
-; CHECK-LE-NEXT:    srlv $2, $2, $4
-; CHECK-LE-NEXT:    not $1, $1
-; CHECK-LE-NEXT:    andi $1, $1, 31
+; CHECK-LE-NEXT:    srlv $2, $2, $1
+; CHECK-LE-NEXT:    not $4, $1
 ; CHECK-LE-NEXT:    sll $6, $5, 1
-; CHECK-LE-NEXT:    sllv $6, $6, $1
+; CHECK-LE-NEXT:    sllv $6, $6, $4
 ; CHECK-LE-NEXT:    or $2, $6, $2
-; CHECK-LE-NEXT:    srlv $4, $5, $4
+; CHECK-LE-NEXT:    srlv $1, $5, $1
 ; CHECK-LE-NEXT:    movz $18, $19, $3
 ; CHECK-LE-NEXT:    sll $3, $18, 1
-; CHECK-LE-NEXT:    sllv $1, $3, $1
-; CHECK-LE-NEXT:    or $3, $1, $4
+; CHECK-LE-NEXT:    sllv $3, $3, $4
+; CHECK-LE-NEXT:    or $3, $3, $1
 ; CHECK-LE-NEXT:    lw $16, 20($sp) # 4-byte Folded Reload
 ; CHECK-LE-NEXT:    lw $17, 24($sp) # 4-byte Folded Reload
 ; CHECK-LE-NEXT:    lw $18, 28($sp) # 4-byte Folded Reload
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/ashr.ll b/llvm/test/CodeGen/Mips/llvm-ir/ashr.ll
index 453ca0d6bab3b18..450fe968d4917c0 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/ashr.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/ashr.ll
@@ -89,51 +89,43 @@ entry:
 define signext i8 @ashr_i8(i8 signext %a, i8 signext %b) {
 ; MIPS-LABEL: ashr_i8:
 ; MIPS:       # %bb.0: # %entry
-; MIPS-NEXT:    andi $1, $5, 255
 ; MIPS-NEXT:    jr $ra
-; MIPS-NEXT:    srav $2, $4, $1
+; MIPS-NEXT:    srav $2, $4, $5
 ;
 ; MIPS32-LABEL: ashr_i8:
 ; MIPS32:       # %bb.0: # %entry
-; MIPS32-NEXT:    andi $1, $5, 255
 ; MIPS32-NEXT:    jr $ra
-; MIPS32-NEXT:    srav $2, $4, $1
+; MIPS32-NEXT:    srav $2, $4, $5
 ;
 ; 32R2-LABEL: ashr_i8:
 ; 32R2:       # %bb.0: # %entry
-; 32R2-NEXT:    andi $1, $5, 255
 ; 32R2-NEXT:    jr $ra
-; 32R2-NEXT:    srav $2, $4, $1
+; 32R2-NEXT:    srav $2, $4, $5
 ;
 ; 32R6-LABEL: ashr_i8:
 ; 32R6:       # %bb.0: # %entry
-; 32R6-NEXT:    andi $1, $5, 255
 ; 32R6-NEXT:    jr $ra
-; 32R6-NEXT:    srav $2, $4, $1
+; 32R6-NEXT:    srav $2, $4, $5
 ;
 ; MIPS3-LABEL: ashr_i8:
 ; MIPS3:       # %bb.0: # %entry
-; MIPS3-NEXT:    andi $1, $5, 255
 ; MIPS3-NEXT:    jr $ra
-; MIPS3-NEXT:    srav $2, $4, $1
+; MIPS3-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64-LABEL: ashr_i8:
 ; MIPS64:       # %bb.0: # %entry
-; MIPS64-NEXT:    andi $1, $5, 255
 ; MIPS64-NEXT:    jr $ra
-; MIPS64-NEXT:    srav $2, $4, $1
+; MIPS64-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64R2-LABEL: ashr_i8:
 ; MIPS64R2:       # %bb.0: # %entry
-; MIPS64R2-NEXT:    andi $1, $5, 255
 ; MIPS64R2-NEXT:    jr $ra
-; MIPS64R2-NEXT:    srav $2, $4, $1
+; MIPS64R2-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64R6-LABEL: ashr_i8:
 ; MIPS64R6:       # %bb.0: # %entry
-; MIPS64R6-NEXT:    andi $1, $5, 255
 ; MIPS64R6-NEXT:    jr $ra
-; MIPS64R6-NEXT:    srav $2, $4, $1
+; MIPS64R6-NEXT:    srav $2, $4, $5
 ;
 ; MMR3-LABEL: ashr_i8:
 ; MMR3:       # %bb.0: # %entry
@@ -155,51 +147,43 @@ entry:
 define signext i16 @ashr_i16(i16 signext %a, i16 signext %b) {
 ; MIPS-LABEL: ashr_i16:
 ; MIPS:       # %bb.0: # %entry
-; MIPS-NEXT:    andi $1, $5, 65535
 ; MIPS-NEXT:    jr $ra
-; MIPS-NEXT:    srav $2, $4, $1
+; MIPS-NEXT:    srav $2, $4, $5
 ;
 ; MIPS32-LABEL: ashr_i16:
 ; MIPS32:       # %bb.0: # %entry
-; MIPS32-NEXT:    andi $1, $5, 65535
 ; MIPS32-NEXT:    jr $ra
-; MIPS32-NEXT:    srav $2, $4, $1
+; MIPS32-NEXT:    srav $2, $4, $5
 ;
 ; 32R2-LABEL: ashr_i16:
 ; 32R2:       # %bb.0: # %entry
-; 32R2-NEXT:    andi $1, $5, 65535
 ; 32R2-NEXT:    jr $ra
-; 32R2-NEXT:    srav $2, $4, $1
+; 32R2-NEXT:    srav $2, $4, $5
 ;
 ; 32R6-LABEL: ashr_i16:
 ; 32R6:       # %bb.0: # %entry
-; 32R6-NEXT:    andi $1, $5, 65535
 ; 32R6-NEXT:    jr $ra
-; 32R6-NEXT:    srav $2, $4, $1
+; 32R6-NEXT:    srav $2, $4, $5
 ;
 ; MIPS3-LABEL: ashr_i16:
 ; MIPS3:       # %bb.0: # %entry
-; MIPS3-NEXT:    andi $1, $5, 65535
 ; MIPS3-NEXT:    jr $ra
-; MIPS3-NEXT:    srav $2, $4, $1
+; MIPS3-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64-LABEL: ashr_i16:
 ; MIPS64:       # %bb.0: # %entry
-; MIPS64-NEXT:    andi $1, $5, 65535
 ; MIPS64-NEXT:    jr $ra
-; MIPS64-NEXT:    srav $2, $4, $1
+; MIPS64-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64R2-LABEL: ashr_i16:
 ; MIPS64R2:       # %bb.0: # %entry
-; MIPS64R2-NEXT:    andi $1, $5, 65535
 ; MIPS64R2-NEXT:    jr $ra
-; MIPS64R2-NEXT:    srav $2, $4, $1
+; MIPS64R2-NEXT:    srav $2, $4, $5
 ;
 ; MIPS64R6-LABEL: ashr_i16:
 ; MIPS64R6:       # %bb.0: # %entry
-; MIPS64R6-NEXT:    andi $1, $5, 65535
 ; MIPS64R6-NEXT:    jr $ra
-; MIPS64R6-NEXT:    srav $2, $4, $1
+; MIPS64R6-NEXT:    srav $2, $4, $5
 ;
 ; MMR3-LABEL: ashr_i16:
 ; MMR3:       # %bb.0: # %entry
@@ -428,7 +412,6 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS-NEXT:    lwr $5, 11($1)
 ; MIPS-NEXT:    andi $2, $2, 7
 ; MIPS-NEXT:    not $6, $2
-; MIPS-NEXT:    andi $6, $6, 31
 ; MIPS-NEXT:    srlv $7, $5, $2
 ; MIPS-NEXT:    sllv $4, $4, $6
 ; MIPS-NEXT:    srlv $3, $3, $2
@@ -483,7 +466,6 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32-NEXT:    lwr $5, 11($1)
 ; MIPS32-NEXT:    andi $2, $2, 7
 ; MIPS32-NEXT:    not $6, $2
-; MIPS32-NEXT:    andi $6, $6, 31
 ; MIPS32-NEXT:    srlv $7, $5, $2
 ; MIPS32-NEXT:    sllv $4, $4, $6
 ; MIPS32-NEXT:    srlv $3, $3, $2
@@ -537,7 +519,6 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
 ; 32R2-NEXT:    lwr $5, 11($1)
 ; 32R2-NEXT:    andi $2, $2, 7
 ; 32R2-NEXT:    not $6, $2
-; 32R2-NEXT:    andi $6, $6, 31
 ; 32R2-NEXT:    srlv $7, $5, $2
 ; 32R2-NEXT:    sllv $4, $4, $6
 ; 32R2-NEXT:    srlv $3, $3, $2
@@ -581,7 +562,6 @@ define signext i128 @ashr_i128(i128 signext %a, i128 signext %b) {
 ; 32R6-NEXT:    lw $5, 8($1)
 ; 32R6-NEXT:    andi $2, $2, 7
 ; 32R6-NEXT:    not $6, $2
-; 32R6-NEXT:    andi $6, $6, 31
 ; 32R6-NEXT:    srlv $7, $5, $2
 ; 32R6-NEXT:    sllv $4, $4, $6
 ; 32R6-NEXT:    srlv $3, $3, $2
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/lshr.ll b/llvm/test/CodeGen/Mips/llvm-ir/lshr.ll
index ddbb1f217837a46..03cf104e3120c4b 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/lshr.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/lshr.ll
@@ -427,7 +427,6 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS2-NEXT:    lwr $5, 11($1)
 ; MIPS2-NEXT:    andi $2, $2, 7
 ; MIPS2-NEXT:    not $6, $2
-; MIPS2-NEXT:    andi $6, $6, 31
 ; MIPS2-NEXT:    srlv $7, $5, $2
 ; MIPS2-NEXT:    sllv $4, $4, $6
 ; MIPS2-NEXT:    srlv $3, $3, $2
@@ -481,7 +480,6 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32-NEXT:    lwr $5, 11($1)
 ; MIPS32-NEXT:    andi $2, $2, 7
 ; MIPS32-NEXT:    not $6, $2
-; MIPS32-NEXT:    andi $6, $6, 31
 ; MIPS32-NEXT:    srlv $7, $5, $2
 ; MIPS32-NEXT:    sllv $4, $4, $6
 ; MIPS32-NEXT:    srlv $3, $3, $2
@@ -534,7 +532,6 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32R2-NEXT:    lwr $5, 11($1)
 ; MIPS32R2-NEXT:    andi $2, $2, 7
 ; MIPS32R2-NEXT:    not $6, $2
-; MIPS32R2-NEXT:    andi $6, $6, 31
 ; MIPS32R2-NEXT:    srlv $7, $5, $2
 ; MIPS32R2-NEXT:    sllv $4, $4, $6
 ; MIPS32R2-NEXT:    srlv $3, $3, $2
@@ -577,7 +574,6 @@ define signext i128 @lshr_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32R6-NEXT:    lw $5, 8($1)
 ; MIPS32R6-NEXT:    andi $2, $2, 7
 ; MIPS32R6-NEXT:    not $6, $2
-; MIPS32R6-NEXT:    andi $6, $6, 31
 ; MIPS32R6-NEXT:    srlv $7, $5, $2
 ; MIPS32R6-NEXT:    sllv $4, $4, $6
 ; MIPS32R6-NEXT:    srlv $3, $3, $2
diff --git a/llvm/test/CodeGen/Mips/llvm-ir/shl.ll b/llvm/test/CodeGen/Mips/llvm-ir/shl.ll
index 256da0b89e6038c..81f089a52947081 100644
--- a/llvm/test/CodeGen/Mips/llvm-ir/shl.ll
+++ b/llvm/test/CodeGen/Mips/llvm-ir/shl.ll
@@ -94,69 +94,60 @@ entry:
 define signext i8 @shl_i8(i8 signext %a, i8 signext %b) {
 ; MIPS2-LABEL: shl_i8:
 ; MIPS2:       # %bb.0: # %entry
-; MIPS2-NEXT:    andi $1, $5, 255
-; MIPS2-NEXT:    sllv $1, $4, $1
+; MIPS2-NEXT:    sllv $1, $4, $5
 ; MIPS2-NEXT:    sll $1, $1, 24
 ; MIPS2-NEXT:    jr $ra
 ; MIPS2-NEXT:    sra $2, $1, 24
 ;
 ; MIPS32-LABEL: shl_i8:
 ; MIPS32:       # %bb.0: # %entry
-; MIPS32-NEXT:    andi $1, $5, 255
-; MIPS32-NEXT:    sllv $1, $4, $1
+; MIPS32-NEXT:    sllv $1, $4, $5
 ; MIPS32-NEXT:    sll $1, $1, 24
 ; MIPS32-NEXT:    jr $ra
 ; MIPS32-NEXT:    sra $2, $1, 24
 ;
 ; MIPS32R2-LABEL: shl_i8:
 ; MIPS32R2:       # %bb.0: # %entry
-; MIPS32R2-NEXT:    andi $1, $5, 255
-; MIPS32R2-NEXT:    sllv $1, $4, $1
+; MIPS32R2-NEXT:    sllv $1, $4, $5
 ; MIPS32R2-NEXT:    jr $ra
 ; MIPS32R2-NEXT:    seb $2, $1
 ;
 ; MIPS32R6-LABEL: shl_i8:
 ; MIPS32R6:       # %bb.0: # %entry
-; MIPS32R6-NEXT:    andi $1, $5, 255
-; MIPS32R6-NEXT:    sllv $1, $4, $1
+; MIPS32R6-NEXT:    sllv $1, $4, $5
 ; MIPS32R6-NEXT:    jr $ra
 ; MIPS32R6-NEXT:    seb $2, $1
 ;
 ; MIPS3-LABEL: shl_i8:
 ; MIPS3:       # %bb.0: # %entry
-; MIPS3-NEXT:    andi $1, $5, 255
-; MIPS3-NEXT:    sllv $1, $4, $1
+; MIPS3-NEXT:    sllv $1, $4, $5
 ; MIPS3-NEXT:    sll $1, $1, 24
 ; MIPS3-NEXT:    jr $ra
 ; MIPS3-NEXT:    sra $2, $1, 24
 ;
 ; MIPS4-LABEL: shl_i8:
 ; MIPS4:       # %bb.0: # %entry
-; MIPS4-NEXT:    andi $1, $5, 255
-; MIPS4-NEXT:    sllv $1, $4, $1
+; MIPS4-NEXT:    sllv $1, $4, $5
 ; MIPS4-NEXT:    sll $1, $1, 24
 ; MIPS4-NEXT:    jr $ra
 ; MIPS4-NEXT:    sra $2, $1, 24
 ;
 ; MIPS64-LABEL: shl_i8:
 ; MIPS64:       # %bb.0: # %entry
-; MIPS64-NEXT:    andi $1, $5, 255
-; MIPS64-NEXT:    sllv $1, $4, $1
+; MIPS64-NEXT:    sllv $1, $4, $5
 ; MIPS64-NEXT:    sll $1, $1, 24
 ; MIPS64-NEXT:    jr $ra
 ; MIPS64-NEXT:    sra $2, $1, 24
 ;
 ; MIPS64R2-LABEL: shl_i8:
 ; MIPS64R2:       # %bb.0: # %entry
-; MIPS64R2-NEXT:    andi $1, $5, 255
-; MIPS64R2-NEXT:    sllv $1, $4, $1
+; MIPS64R2-NEXT:    sllv $1, $4, $5
 ; MIPS64R2-NEXT:    jr $ra
 ; MIPS64R2-NEXT:    seb $2, $1
 ;
 ; MIPS64R6-LABEL: shl_i8:
 ; MIPS64R6:       # %bb.0: # %entry
-; MIPS64R6-NEXT:    andi $1, $5, 255
-; MIPS64R6-NEXT:    sllv $1, $4, $1
+; MIPS64R6-NEXT:    sllv $1, $4, $5
 ; MIPS64R6-NEXT:    jr $ra
 ; MIPS64R6-NEXT:    seb $2, $1
 ;
@@ -182,69 +173,60 @@ entry:
 define signext i16 @shl_i16(i16 signext %a, i16 signext %b) {
 ; MIPS2-LABEL: shl_i16:
 ; MIPS2:       # %bb.0: # %entry
-; MIPS2-NEXT:    andi $1, $5, 65535
-; MIPS2-NEXT:    sllv $1, $4, $1
+; MIPS2-NEXT:    sllv $1, $4, $5
 ; MIPS2-NEXT:    sll $1, $1, 16
 ; MIPS2-NEXT:    jr $ra
 ; MIPS2-NEXT:    sra $2, $1, 16
 ;
 ; MIPS32-LABEL: shl_i16:
 ; MIPS32:       # %bb.0: # %entry
-; MIPS32-NEXT:    andi $1, $5, 65535
-; MIPS32-NEXT:    sllv $1, $4, $1
+; MIPS32-NEXT:    sllv $1, $4, $5
 ; MIPS32-NEXT:    sll $1, $1, 16
 ; MIPS32-NEXT:    jr $ra
 ; MIPS32-NEXT:    sra $2, $1, 16
 ;
 ; MIPS32R2-LABEL: shl_i16:
 ; MIPS32R2:       # %bb.0: # %entry
-; MIPS32R2-NEXT:    andi $1, $5, 65535
-; MIPS32R2-NEXT:    sllv $1, $4, $1
+; MIPS32R2-NEXT:    sllv $1, $4, $5
 ; MIPS32R2-NEXT:    jr $ra
 ; MIPS32R2-NEXT:    seh $2, $1
 ;
 ; MIPS32R6-LABEL: shl_i16:
 ; MIPS32R6:       # %bb.0: # %entry
-; MIPS32R6-NEXT:    andi $1, $5, 65535
-; MIPS32R6-NEXT:    sllv $1, $4, $1
+; MIPS32R6-NEXT:    sllv $1, $4, $5
 ; MIPS32R6-NEXT:    jr $ra
 ; MIPS32R6-NEXT:    seh $2, $1
 ;
 ; MIPS3-LABEL: shl_i16:
 ; MIPS3:       # %bb.0: # %entry
-; MIPS3-NEXT:    andi $1, $5, 65535
-; MIPS3-NEXT:    sllv $1, $4, $1
+; MIPS3-NEXT:    sllv $1, $4, $5
 ; MIPS3-NEXT:    sll $1, $1, 16
 ; MIPS3-NEXT:    jr $ra
 ; MIPS3-NEXT:    sra $2, $1, 16
 ;
 ; MIPS4-LABEL: shl_i16:
 ; MIPS4:       # %bb.0: # %entry
-; MIPS4-NEXT:    andi $1, $5, 65535
-; MIPS4-NEXT:    sllv $1, $4, $1
+; MIPS4-NEXT:    sllv $1, $4, $5
 ; MIPS4-NEXT:    sll $1, $1, 16
 ; MIPS4-NEXT:    jr $ra
 ; MIPS4-NEXT:    sra $2, $1, 16
 ;
 ; MIPS64-LABEL: shl_i16:
 ; MIPS64:       # %bb.0: # %entry
-; MIPS64-NEXT:    andi $1, $5, 65535
-; MIPS64-NEXT:    sllv $1, $4, $1
+; MIPS64-NEXT:    sllv $1, $4, $5
 ; MIPS64-NEXT:    sll $1, $1, 16
 ; MIPS64-NEXT:    jr $ra
 ; MIPS64-NEXT:    sra $2, $1, 16
 ;
 ; MIPS64R2-LABEL: shl_i16:
 ; MIPS64R2:       # %bb.0: # %entry
-; MIPS64R2-NEXT:    andi $1, $5, 65535
-; MIPS64R2-NEXT:    sllv $1, $4, $1
+; MIPS64R2-NEXT:    sllv $1, $4, $5
 ; MIPS64R2-NEXT:    jr $ra
 ; MIPS64R2-NEXT:    seh $2, $1
 ;
 ; MIPS64R6-LABEL: shl_i16:
 ; MIPS64R6:       # %bb.0: # %entry
-; MIPS64R6-NEXT:    andi $1, $5, 65535
-; MIPS64R6-NEXT:    sllv $1, $4, $1
+; MIPS64R6-NEXT:    sllv $1, $4, $5
 ; MIPS64R6-NEXT:    jr $ra
 ; MIPS64R6-NEXT:    seh $2, $1
 ;
@@ -486,7 +468,6 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
 ; MIPS2-NEXT:    lwr $3, 7($4)
 ; MIPS2-NEXT:    andi $1, $1, 7
 ; MIPS2-NEXT:    not $6, $1
-; MIPS2-NEXT:    andi $6, $6, 31
 ; MIPS2-NEXT:    sllv $7, $3, $1
 ; MIPS2-NEXT:    srlv $6, $2, $6
 ; MIPS2-NEXT:    lwl $2, 0($4)
@@ -539,7 +520,6 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32-NEXT:    lwr $3, 7($4)
 ; MIPS32-NEXT:    andi $1, $1, 7
 ; MIPS32-NEXT:    not $6, $1
-; MIPS32-NEXT:    andi $6, $6, 31
 ; MIPS32-NEXT:    sllv $7, $3, $1
 ; MIPS32-NEXT:    srlv $6, $2, $6
 ; MIPS32-NEXT:    lwl $2, 0($4)
@@ -591,7 +571,6 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32R2-NEXT:    lwr $3, 7($4)
 ; MIPS32R2-NEXT:    andi $1, $1, 7
 ; MIPS32R2-NEXT:    not $6, $1
-; MIPS32R2-NEXT:    andi $6, $6, 31
 ; MIPS32R2-NEXT:    sllv $7, $3, $1
 ; MIPS32R2-NEXT:    srlv $6, $2, $6
 ; MIPS32R2-NEXT:    lwl $2, 0($4)
@@ -633,7 +612,6 @@ define signext i128 @shl_i128(i128 signext %a, i128 signext %b) {
 ; MIPS32R6-NEXT:    lw $3, 4($4)
 ; MIPS32R6-NEXT:    andi $1, $1, 7
 ; MIPS32R6-NEXT:    not $6, $1
-; MIPS32R6-NEXT:    andi $6, $6, 31
 ; MIPS32R6-NEXT:    sllv $7, $3, $1
 ; MIPS32R6-NEXT:    srlv $6, $2, $6
 ; MIPS32R6-NEXT:    lw $2, 0($4)
diff --git a/llvm/test/CodeGen/Mips/optimizeAndPlusShift.ll b/llvm/test/CodeGen/Mips/optimizeAndPlusShift.ll
new file mode 100644
index 000000000000000..bf69adf6702f0ac
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/optimizeAndPlusShift.ll
@@ -0,0 +1,84 @@
+; RUN: llc < %s -mtriple=mipsel-unknown-linux-gnu | FileCheck %s --check-prefixes=MIPS32
+; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnuabi64 | FileCheck %s --check-prefixes=MIPS64
+; RUN: llc < %s -mtriple=mips64el-unknown-linux-gnuabi64 | FileCheck %s --check-prefixes=MIPS64
+
+define i32 @shl_32(i32 %a, i32 %b) {
+; MIPS32-LABLE:   shl_32:
+; MIPS32:	  # %bb.0:
+; MIPS32-NEXT:    jr	$ra
+; MIPS32-NEXT:    sllv	$2, $4, $5
+; MIPS64-LABLE:   shl_32:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    sll   $2, $4, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    sllv	$2, $2, $1
+  %_1 = and i32 %b, 31
+  %_0 = shl i32 %a, %_1
+  ret i32 %_0
+}
+
+define i32 @lshr_32(i32 %a, i32 %b) {
+; MIPS32-LABLE:   lshr_32:
+; MIPS32:	  # %bb.0:
+; MIPS32-NEXT:    jr	$ra
+; MIPS32-NEXT:    srlv	$2, $4, $5
+; MIPS64-LABLE:   lshr_32:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    sll   $2, $4, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    srlv	$2, $2, $1
+  %_1 = and i32 %b, 31
+  %_0 = lshr i32 %a, %_1
+  ret i32 %_0
+}
+
+define i32 @ashr_32(i32 %a, i32 %b) {
+; MIPS32-LABLE:   ashr_32:
+; MIPS32:	  # %bb.0:
+; MIPS32-NEXT:    jr	$ra
+; MIPS32-NEXT:    srav	$2, $4, $5
+; MIPS64-LABLE:   ashr_32:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    sll   $2, $4, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    srav	$2, $2, $1
+  %_1 = and i32 %b, 31
+  %_0 = ashr i32 %a, %_1
+  ret i32 %_0
+}
+
+define i64 @shl_64(i64 %a, i64 %b) {
+; MIPS64-LABLE:   shl_64:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    dsllv	$2, $4, $1
+  %_1 = and i64 %b, 63
+  %_0 = shl i64 %a, %_1
+  ret i64 %_0
+}
+
+define i64 @lshr_64(i64 %a, i64 %b) {
+; MIPS64-LABLE:   lshr_64:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    dsrlv	$2, $4, $1
+  %_1 = and i64 %b, 63
+  %_0 = lshr i64 %a, %_1
+  ret i64 %_0
+}
+
+define i64 @ashr_64(i64 %a, i64 %b) {
+; MIPS64-LABLE:   ashr_64:
+; MIPS64:	  # %bb.0:
+; MIPS64-NEXT:    sll   $1, $5, 0
+; MIPS64-NEXT:    jr	$ra
+; MIPS64-NEXT:    dsrav	$2, $4, $1
+  %_1 = and i64 %b, 63
+  %_0 = ashr i64 %a, %_1
+  ret i64 %_0
+}



More information about the llvm-commits mailing list