[llvm] [DAGCombiner] Port custom DAG combine for `rem` from NVPTX (PR #210344)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 20 00:07:16 PDT 2026


https://github.com/def3r updated https://github.com/llvm/llvm-project/pull/210344

>From d43613a56b42f438ab07c6b6e8b771e76385e873 Mon Sep 17 00:00:00 2001
From: Ayaan Khan <ayaanandayaan2 at gmail.com>
Date: Fri, 17 Jul 2026 18:54:12 +0530
Subject: [PATCH 1/2] port div rem combine from NVPTX

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 36 +++++++++
 llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp   | 37 +--------
 llvm/test/CodeGen/X86/divide-by-constant.ll   | 59 ++++++--------
 llvm/test/CodeGen/X86/divrem.ll               | 76 +++++++++++--------
 4 files changed, 105 insertions(+), 103 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 2f2d5cb709642..f5388a2982bde 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -444,6 +444,7 @@ namespace {
     SDValue visitSSUBO_CARRY(SDNode *N);
     SDValue visitMUL(SDNode *N);
     SDValue visitMULFIX(SDNode *N);
+    SDValue performREMCombine(SDNode *N);
     SDValue useDivRem(SDNode *N);
     SDValue visitSDIV(SDNode *N);
     SDValue visitSDIVLike(SDValue N0, SDValue N1, SDNode *N);
@@ -5093,6 +5094,38 @@ static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned,
   return DAG.getLibcalls().getLibcallImpl(LC) != RTLIB::Unsupported;
 }
 
+// Fold Num % Den -> Num - (Num / Den) * Den, if (Num / Den) is already
+// computed
+SDValue DAGCombiner::performREMCombine(SDNode *N) {
+  assert(N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM);
+
+  // Don't do anything at less than -O2.
+  if (OptLevel < CodeGenOptLevel::Default)
+    return SDValue();
+
+  SDLoc DL(N);
+  EVT VT = N->getValueType(0);
+  bool IsSigned = N->getOpcode() == ISD::SREM;
+  unsigned DivOpc = IsSigned ? ISD::SDIV : ISD::UDIV;
+  unsigned DivRemOpc = IsSigned ? ISD::SDIVREM : ISD::UDIVREM;
+
+  // If DIVREM is available, do not fold
+  if (TLI.isOperationLegalOrCustom(DivRemOpc, VT.getScalarType()))
+    return SDValue();
+
+  const SDValue &Num = N->getOperand(0);
+  const SDValue &Den = N->getOperand(1);
+  for (const SDNode *U : Num->users()) {
+    if (U->getOpcode() == DivOpc && U->getOperand(0) == Num &&
+        U->getOperand(1) == Den) {
+      SDValue Div = DAG.getNode(DivOpc, DL, VT, Num, Den);
+      SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Div, Den);
+      return DAG.getNode(ISD::SUB, DL, VT, Num, Mul);
+    }
+  }
+  return SDValue();
+}
+
 /// Issue divrem if both quotient and remainder are needed.
 SDValue DAGCombiner::useDivRem(SDNode *Node) {
   if (Node->use_empty())
@@ -5563,6 +5596,9 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
     }
   }
 
+  if (SDValue V = performREMCombine(N))
+    return V;
+
   // sdiv, srem -> sdivrem
   if (SDValue DivRem = useDivRem(N))
     return DivRem.getValue(1);
diff --git a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
index 1c5caf124c17e..522620d88227f 100644
--- a/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
+++ b/llvm/lib/Target/NVPTX/NVPTXISelLowering.cpp
@@ -687,6 +687,9 @@ NVPTXTargetLowering::NVPTXTargetLowering(const NVPTXTargetMachine &TM,
     setOperationAction(ISD::BR_CC, VT, Expand);
   }
 
+  setOperationAction(ISD::SDIVREM, {MVT::i32, MVT::i64}, Expand);
+  setOperationAction(ISD::UDIVREM, {MVT::i32, MVT::i64}, Expand);
+
   // We don't want ops like FMINIMUM or UMAX to be lowered to SETCC+VSELECT.
   setOperationAction(ISD::VSELECT, {MVT::v2f32, MVT::v2i32}, Expand);
 
@@ -6281,37 +6284,6 @@ static SDValue PerformFMinMaxCombine(SDNode *N,
   return SDValue();
 }
 
-static SDValue PerformREMCombine(SDNode *N,
-                                 TargetLowering::DAGCombinerInfo &DCI,
-                                 CodeGenOptLevel OptLevel) {
-  assert(N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM);
-
-  // Don't do anything at less than -O2.
-  if (OptLevel < CodeGenOptLevel::Default)
-    return SDValue();
-
-  SelectionDAG &DAG = DCI.DAG;
-  SDLoc DL(N);
-  EVT VT = N->getValueType(0);
-  bool IsSigned = N->getOpcode() == ISD::SREM;
-  unsigned DivOpc = IsSigned ? ISD::SDIV : ISD::UDIV;
-
-  const SDValue &Num = N->getOperand(0);
-  const SDValue &Den = N->getOperand(1);
-
-  for (const SDNode *U : Num->users()) {
-    if (U->getOpcode() == DivOpc && U->getOperand(0) == Num &&
-        U->getOperand(1) == Den) {
-      // Num % Den -> Num - (Num / Den) * Den
-      return DAG.getNode(ISD::SUB, DL, VT, Num,
-                         DAG.getNode(ISD::MUL, DL, VT,
-                                     DAG.getNode(DivOpc, DL, VT, Num, Den),
-                                     Den));
-    }
-  }
-  return SDValue();
-}
-
 // sext (mul.iN nsw x, y)     => mul.wide.sN x, y
 // zext (mul.iN nuw x, y)     => mul.wide.uN x, y
 // sext (shl.iN nsw x, const) => mul.wide.sN x, (1 << const)
@@ -7121,9 +7093,6 @@ SDValue NVPTXTargetLowering::PerformDAGCombine(SDNode *N,
     return PerformSETCCCombine(N, DCI, STI.getSmVersion());
   case ISD::SHL:
     return PerformSHLCombine(N, DCI, OptLevel);
-  case ISD::SREM:
-  case ISD::UREM:
-    return PerformREMCombine(N, DCI, OptLevel);
   case ISD::STORE:
   case NVPTXISD::StoreV2:
   case NVPTXISD::StoreV4:
diff --git a/llvm/test/CodeGen/X86/divide-by-constant.ll b/llvm/test/CodeGen/X86/divide-by-constant.ll
index d9e19df39f6b6..4dee2fdc872c7 100644
--- a/llvm/test/CodeGen/X86/divide-by-constant.ll
+++ b/llvm/test/CodeGen/X86/divide-by-constant.ll
@@ -410,40 +410,40 @@ define { i64, i32 } @PR38622(i64) nounwind {
 ; X86-NEXT:    pushl %esi
 ; X86-NEXT:    pushl %eax
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
-; X86-NEXT:    movl %ecx, %ebx
-; X86-NEXT:    shrdl $11, %edi, %ebx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
+; X86-NEXT:    movl %ecx, %edi
+; X86-NEXT:    shrdl $11, %ebx, %edi
 ; X86-NEXT:    movl $1125899, %edx # imm = 0x112E0B
-; X86-NEXT:    movl %ebx, %eax
+; X86-NEXT:    movl %edi, %eax
 ; X86-NEXT:    mull %edx
 ; X86-NEXT:    movl %eax, (%esp) # 4-byte Spill
 ; X86-NEXT:    movl %edx, %esi
 ; X86-NEXT:    movl $-400107883, %edx # imm = 0xE826D695
-; X86-NEXT:    movl %ebx, %eax
+; X86-NEXT:    movl %edi, %eax
 ; X86-NEXT:    mull %edx
 ; X86-NEXT:    movl %edx, %ebp
 ; X86-NEXT:    addl (%esp), %ebp # 4-byte Folded Reload
 ; X86-NEXT:    adcl $0, %esi
-; X86-NEXT:    shrl $11, %edi
-; X86-NEXT:    movl %edi, %eax
+; X86-NEXT:    shrl $11, %ebx
+; X86-NEXT:    movl %ebx, %eax
 ; X86-NEXT:    movl $1125899, %edx # imm = 0x112E0B
 ; X86-NEXT:    mull %edx
-; X86-NEXT:    movl %edx, %ebx
+; X86-NEXT:    movl %edx, %edi
 ; X86-NEXT:    movl %eax, (%esp) # 4-byte Spill
-; X86-NEXT:    movl %edi, %eax
+; X86-NEXT:    movl %ebx, %eax
 ; X86-NEXT:    movl $-400107883, %edx # imm = 0xE826D695
 ; X86-NEXT:    mull %edx
 ; X86-NEXT:    addl %ebp, %eax
 ; X86-NEXT:    adcl %edx, %esi
-; X86-NEXT:    adcl $0, %ebx
+; X86-NEXT:    adcl $0, %edi
 ; X86-NEXT:    addl (%esp), %esi # 4-byte Folded Reload
-; X86-NEXT:    adcl $0, %ebx
-; X86-NEXT:    shrdl $9, %ebx, %esi
+; X86-NEXT:    adcl $0, %edi
+; X86-NEXT:    shrdl $9, %edi, %esi
 ; X86-NEXT:    imull $-294967296, %esi, %eax # imm = 0xEE6B2800
 ; X86-NEXT:    subl %eax, %ecx
-; X86-NEXT:    shrl $9, %ebx
+; X86-NEXT:    shrl $9, %edi
 ; X86-NEXT:    movl %esi, %eax
-; X86-NEXT:    movl %ebx, %edx
+; X86-NEXT:    movl %edi, %edx
 ; X86-NEXT:    addl $4, %esp
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
@@ -474,35 +474,20 @@ define { i64, i32 } @PR38622(i64) nounwind {
 define { i64, i32 } @PR38622_signed(i64) nounwind {
 ; X86-LABEL: PR38622_signed:
 ; X86:       # %bb.0:
-; X86-NEXT:    pushl %ebp
-; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
-; X86-NEXT:    subl $12, %esp
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebp
+; X86-NEXT:    subl $8, %esp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
 ; X86-NEXT:    pushl $0
 ; X86-NEXT:    pushl $-294967296 # imm = 0xEE6B2800
-; X86-NEXT:    pushl %ebp
-; X86-NEXT:    pushl %ebx
+; X86-NEXT:    pushl {{[0-9]+}}(%esp)
+; X86-NEXT:    pushl %esi
 ; X86-NEXT:    calll __divdi3
 ; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl %eax, %esi
-; X86-NEXT:    movl %edx, %edi
-; X86-NEXT:    pushl $0
-; X86-NEXT:    pushl $-294967296 # imm = 0xEE6B2800
-; X86-NEXT:    pushl %ebp
-; X86-NEXT:    pushl %ebx
-; X86-NEXT:    calll __moddi3
-; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl %eax, %ecx
-; X86-NEXT:    movl %esi, %eax
-; X86-NEXT:    movl %edi, %edx
-; X86-NEXT:    addl $12, %esp
+; X86-NEXT:    imull $-294967296, %eax, %ecx # imm = 0xEE6B2800
+; X86-NEXT:    subl %ecx, %esi
+; X86-NEXT:    movl %esi, %ecx
+; X86-NEXT:    addl $8, %esp
 ; X86-NEXT:    popl %esi
-; X86-NEXT:    popl %edi
-; X86-NEXT:    popl %ebx
-; X86-NEXT:    popl %ebp
 ; X86-NEXT:    retl
 ;
 ; X64-LABEL: PR38622_signed:
diff --git a/llvm/test/CodeGen/X86/divrem.ll b/llvm/test/CodeGen/X86/divrem.ll
index ba777b4954611..8e21e75b3f3d8 100644
--- a/llvm/test/CodeGen/X86/divrem.ll
+++ b/llvm/test/CodeGen/X86/divrem.ll
@@ -9,28 +9,34 @@ define void @si64(i64 %x, i64 %y, ptr %p, ptr %q) nounwind {
 ; X86-NEXT:    pushl %ebx
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
+; X86-NEXT:    pushl %eax
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; X86-NEXT:    pushl %edi
+; X86-NEXT:    pushl %esi
 ; X86-NEXT:    pushl %ebp
 ; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
 ; X86-NEXT:    calll __divdi3
 ; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl %eax, %esi
-; X86-NEXT:    movl %edx, %edi
-; X86-NEXT:    pushl %ebp
-; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    calll __moddi3
-; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %edi, 4(%ecx)
-; X86-NEXT:    movl %esi, (%ecx)
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %edx, 4(%ecx)
-; X86-NEXT:    movl %eax, (%ecx)
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    movl %edx, (%esp) # 4-byte Spill
+; X86-NEXT:    imull %eax, %edi
+; X86-NEXT:    mull %esi
+; X86-NEXT:    addl %edi, %edx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; X86-NEXT:    movl %ecx, (%edi)
+; X86-NEXT:    movl (%esp), %ecx # 4-byte Reload
+; X86-NEXT:    movl %ecx, 4(%edi)
+; X86-NEXT:    imull %ecx, %esi
+; X86-NEXT:    addl %edx, %esi
+; X86-NEXT:    subl %eax, %ebx
+; X86-NEXT:    sbbl %esi, %ebp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %ebx, (%eax)
+; X86-NEXT:    movl %ebp, 4(%eax)
+; X86-NEXT:    addl $4, %esp
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    popl %ebx
@@ -150,28 +156,34 @@ define void @ui64(i64 %x, i64 %y, ptr %p, ptr %q) nounwind {
 ; X86-NEXT:    pushl %ebx
 ; X86-NEXT:    pushl %edi
 ; X86-NEXT:    pushl %esi
+; X86-NEXT:    pushl %eax
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebx
 ; X86-NEXT:    movl {{[0-9]+}}(%esp), %ebp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; X86-NEXT:    pushl %edi
+; X86-NEXT:    pushl %esi
 ; X86-NEXT:    pushl %ebp
 ; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
 ; X86-NEXT:    calll __udivdi3
 ; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl %eax, %esi
-; X86-NEXT:    movl %edx, %edi
-; X86-NEXT:    pushl %ebp
-; X86-NEXT:    pushl %ebx
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    pushl {{[0-9]+}}(%esp)
-; X86-NEXT:    calll __umoddi3
-; X86-NEXT:    addl $16, %esp
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %edi, 4(%ecx)
-; X86-NEXT:    movl %esi, (%ecx)
-; X86-NEXT:    movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT:    movl %edx, 4(%ecx)
-; X86-NEXT:    movl %eax, (%ecx)
+; X86-NEXT:    movl %eax, %ecx
+; X86-NEXT:    movl %edx, (%esp) # 4-byte Spill
+; X86-NEXT:    imull %eax, %edi
+; X86-NEXT:    mull %esi
+; X86-NEXT:    addl %edi, %edx
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %edi
+; X86-NEXT:    movl %ecx, (%edi)
+; X86-NEXT:    movl (%esp), %ecx # 4-byte Reload
+; X86-NEXT:    movl %ecx, 4(%edi)
+; X86-NEXT:    imull %ecx, %esi
+; X86-NEXT:    addl %edx, %esi
+; X86-NEXT:    subl %eax, %ebx
+; X86-NEXT:    sbbl %esi, %ebp
+; X86-NEXT:    movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT:    movl %ebx, (%eax)
+; X86-NEXT:    movl %ebp, 4(%eax)
+; X86-NEXT:    addl $4, %esp
 ; X86-NEXT:    popl %esi
 ; X86-NEXT:    popl %edi
 ; X86-NEXT:    popl %ebx

>From c8f33aed03b0ec4bd0b54cb9eb65abe37811e0fc Mon Sep 17 00:00:00 2001
From: Ayaan Khan <ayaanandayaan2 at gmail.com>
Date: Sun, 19 Jul 2026 12:16:33 +0530
Subject: [PATCH 2/2] update tests + embed fold logic in visitREM

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp |  53 +--
 llvm/test/CodeGen/ARM/divmod-eabi.ll          |  18 +-
 llvm/test/CodeGen/Mips/divrem.ll              |  64 ++--
 llvm/test/CodeGen/NVPTX/divrem-combine.ll     |   7 +-
 .../test/CodeGen/PowerPC/p10-vector-modulo.ll |  28 +-
 llvm/test/CodeGen/PowerPC/ppc64-P9-mod.ll     |  10 +-
 llvm/test/CodeGen/PowerPC/srem-vector-lkk.ll  | 341 ++++++++----------
 llvm/test/CodeGen/PowerPC/urem-vector-lkk.ll  | 211 +++++------
 llvm/test/CodeGen/RISCV/srem-lkk.ll           |  42 +--
 llvm/test/CodeGen/RISCV/srem-vector-lkk.ll    | 108 +++---
 llvm/test/CodeGen/RISCV/urem-lkk.ll           |  38 +-
 llvm/test/CodeGen/RISCV/urem-vector-lkk.ll    | 108 +++---
 12 files changed, 473 insertions(+), 555 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index f5388a2982bde..ace22b74c592b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -444,7 +444,6 @@ namespace {
     SDValue visitSSUBO_CARRY(SDNode *N);
     SDValue visitMUL(SDNode *N);
     SDValue visitMULFIX(SDNode *N);
-    SDValue performREMCombine(SDNode *N);
     SDValue useDivRem(SDNode *N);
     SDValue visitSDIV(SDNode *N);
     SDValue visitSDIVLike(SDValue N0, SDValue N1, SDNode *N);
@@ -5094,38 +5093,6 @@ static bool isDivRemLibcallAvailable(SDNode *Node, bool isSigned,
   return DAG.getLibcalls().getLibcallImpl(LC) != RTLIB::Unsupported;
 }
 
-// Fold Num % Den -> Num - (Num / Den) * Den, if (Num / Den) is already
-// computed
-SDValue DAGCombiner::performREMCombine(SDNode *N) {
-  assert(N->getOpcode() == ISD::SREM || N->getOpcode() == ISD::UREM);
-
-  // Don't do anything at less than -O2.
-  if (OptLevel < CodeGenOptLevel::Default)
-    return SDValue();
-
-  SDLoc DL(N);
-  EVT VT = N->getValueType(0);
-  bool IsSigned = N->getOpcode() == ISD::SREM;
-  unsigned DivOpc = IsSigned ? ISD::SDIV : ISD::UDIV;
-  unsigned DivRemOpc = IsSigned ? ISD::SDIVREM : ISD::UDIVREM;
-
-  // If DIVREM is available, do not fold
-  if (TLI.isOperationLegalOrCustom(DivRemOpc, VT.getScalarType()))
-    return SDValue();
-
-  const SDValue &Num = N->getOperand(0);
-  const SDValue &Den = N->getOperand(1);
-  for (const SDNode *U : Num->users()) {
-    if (U->getOpcode() == DivOpc && U->getOperand(0) == Num &&
-        U->getOperand(1) == Den) {
-      SDValue Div = DAG.getNode(DivOpc, DL, VT, Num, Den);
-      SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Div, Den);
-      return DAG.getNode(ISD::SUB, DL, VT, Num, Mul);
-    }
-  }
-  return SDValue();
-}
-
 /// Issue divrem if both quotient and remainder are needed.
 SDValue DAGCombiner::useDivRem(SDNode *Node) {
   if (Node->use_empty())
@@ -5596,8 +5563,24 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
     }
   }
 
-  if (SDValue V = performREMCombine(N))
-    return V;
+  // Fold Num % Den -> Num - (Num / Den) * Den, if (Num / Den) is already
+  // computed. Defer for types that will be promoted and do not fold if DIVREM
+  // is available
+  unsigned DivRemOpc = isSigned ? ISD::SDIVREM : ISD::UDIVREM;
+  if (TLI.getTypeAction(*DAG.getContext(), VT) !=
+          TargetLowering::TypePromoteInteger &&
+      !TLI.isOperationLegalOrCustom(DivRemOpc, VT.getScalarType()) &&
+      !isDivRemLibcallAvailable(N, isSigned, DAG)) {
+    unsigned DivOpc = isSigned ? ISD::SDIV : ISD::UDIV;
+    for (const SDNode *U : N0->users()) {
+      if (U->getOpcode() == DivOpc && U->getOperand(0) == N0 &&
+          U->getOperand(1) == N1) {
+        SDValue Div = DAG.getNode(DivOpc, DL, VT, N0, N1);
+        SDValue Mul = DAG.getNode(ISD::MUL, DL, VT, Div, N1);
+        return DAG.getNode(ISD::SUB, DL, VT, N0, Mul);
+      }
+    }
+  }
 
   // sdiv, srem -> sdivrem
   if (SDValue DivRem = useDivRem(N))
diff --git a/llvm/test/CodeGen/ARM/divmod-eabi.ll b/llvm/test/CodeGen/ARM/divmod-eabi.ll
index a7bfed7290e2a..e3fd66d4140db 100644
--- a/llvm/test/CodeGen/ARM/divmod-eabi.ll
+++ b/llvm/test/CodeGen/ARM/divmod-eabi.ll
@@ -133,15 +133,21 @@ entry:
 ; EABI-NEXT: adc r1
 ; EABI-NOT: __aeabi_ldivmod
 ; DARWIN: ___divdi3
-; DARWIN: mov [[div1:r[0-9]+]], r0
-; DARWIN: mov [[div2:r[0-9]+]], r1
-; DARWIN: __moddi3
+; DARWIN: umull
+; DARWIN: mla
+; DARWIN: subs
+; DARWIN: mla
+; DARWIN: sbc
 ; DARWIN-O0: __divdi3
-; DARWIN-O0: __moddi3
+; DARWIN-O0: umull
+; DARWIN-O0: mla
+; DARWIN-O0: mla
+; DARWIN-O0: subs
+; DARWIN-O0: sbc
 ; WINDOWS: __rt_sdiv64
   %add = add nsw i64 %rem, %div
-; DARWIN: adds r0{{.*}}[[div1]]
-; DARWIN: adc r1{{.*}}[[div2]]
+; DARWIN: adds r0
+; DARWIN: adc r1
 ; WINDOWS: adds r0, r0, r2
 ; WINDOWS: adcs r1, r3
   ret i64 %add
diff --git a/llvm/test/CodeGen/Mips/divrem.ll b/llvm/test/CodeGen/Mips/divrem.ll
index a29f2793c081f..a41e998e54cd7 100644
--- a/llvm/test/CodeGen/Mips/divrem.ll
+++ b/llvm/test/CodeGen/Mips/divrem.ll
@@ -152,20 +152,19 @@ entry:
 ; ACC64:         mfhi $[[R0:[0-9]+]]
 ; ACC64:         sw $[[R0]], 0(${{[0-9]+}})
 
-; GPR32-DAG:     mod $[[R0:[0-9]+]], $4, $5
+; GPR32-DAG:     div $[[R0:[0-9]+]], $4, $5
 ; GPR32-TRAP:    teq $5, $zero, 7
+; GPR32-DAG:     mul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR32-DAG:     subu $[[R2:[0-9]+]], $4, $[[R1]]
 ; NOCHECK-NOT:   teq
-; GPR32:         sw $[[R0]], 0(${{[0-9]+}})
-; GPR32-DAG:     div $2, $4, $5
-; GPR32-TRAP:    teq $5, $zero, 7
+; GPR32:         sw $[[R2]], 0(${{[0-9]+}})
 
-; GPR64-DAG:     mod $[[R0:[0-9]+]], $4, $5
-; GPR64-TRAP:    teq $5, $zero, 7
-; NOCHECK-NOT:   teq
-; GPR64:         sw $[[R0]], 0(${{[0-9]+}})
-; GPR64-DAG:     div $2, $4, $5
+; GPR64-DAG:     div $[[R0:[0-9]+]], $4, $5
 ; GPR64-TRAP:    teq $5, $zero, 7
+; GPR64-DAG:     mul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR64-DAG:     subu $[[R2:[0-9]+]], $4, $[[R1]]
 ; NOCHECK-NOT:   teq
+; GPR64:         sw $[[R2]], 0(${{[0-9]+}})
 
 ; ALL: .end sdivrem1
 
@@ -193,21 +192,20 @@ entry:
 ; ACC64:         mfhi $[[R0:[0-9]+]]
 ; ACC64:         sw $[[R0]], 0(${{[0-9]+}})
 
-; GPR32-DAG:     modu $[[R0:[0-9]+]], $4, $5
-; GPR32-TRAP:    teq $5, $zero, 7
-; GPR32:         sw $[[R0]], 0(${{[0-9]+}})
-; NOCHECK-NOT:   teq
-; GPR32-DAG:     divu $2, $4, $5
+; NOCHECK-NOT:   mod
+; GPR32-DAG:     divu $[[R0:[0-9]+]], $4, $5
 ; GPR32-TRAP:    teq $5, $zero, 7
+; GPR32-DAG:     mul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR32-DAG:     subu $[[R2:[0-9]+]], $4, $[[R1]]
+; GPR32:         sw $[[R2]], 0(${{[0-9]+}})
 ; NOCHECK-NOT:   teq
 
-; GPR64-DAG:     modu $[[R0:[0-9]+]], $4, $5
-; GPR64-TRAP:    teq $5, $zero, 7
-; NOCHECK-NOT:   teq
-; GPR64:         sw $[[R0]], 0(${{[0-9]+}})
-; GPR64-DAG:     divu $2, $4, $5
+; GPR64-DAG:     divu $[[R0:[0-9]+]], $4, $5
 ; GPR64-TRAP:    teq $5, $zero, 7
+; GPR64-DAG:     mul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR64-DAG:     subu $[[R2:[0-9]+]], $4, $[[R1]]
 ; NOCHECK-NOT:   teq
+; GPR64:         sw $[[R2]], 0(${{[0-9]+}})
 
 ; ALL: .end udivrem1
 
@@ -323,10 +321,10 @@ entry:
 
 ; sdivrem2 is too complex to effectively check. We can at least check for the
 ; calls though.
-; ACC32:         lw $25, %call16(__moddi3)(
-; ACC32:         jalr $25
 ; ACC32:         lw $25, %call16(__divdi3)(
 ; ACC32:         jalr $25
+; ACC32:         mul
+; ACC32:         subu
 
 ; ACC64:         ddiv $zero, $4, $5
 ; ACC64-TRAP:    teq $5, $zero, 7
@@ -335,14 +333,12 @@ entry:
 ; ACC64:         mfhi $[[R0:[0-9]+]]
 ; ACC64:         sd $[[R0]], 0(${{[0-9]+}})
 
-; GPR64-DAG:     dmod $[[R0:[0-9]+]], $4, $5
-; GPR64-TRAP:    teq $5, $zero, 7
-; NOCHECK-NOT:   teq
-; GPR64:         sd $[[R0]], 0(${{[0-9]+}})
-
-; GPR64-DAG:     ddiv $2, $4, $5
+; GPR64-DAG:     ddiv $[[R0:[0-9]+]], $4, $5
 ; GPR64-TRAP:    teq $5, $zero, 7
 ; NOCHECK-NOT:   teq
+; GPR64-DAG:     dmul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR64-DAG:     dsubu $[[R2:[0-9]+]], $4, $[[R1]]
+; GPR64:         sd $[[R2]], 0(${{[0-9]+}})
 
 ; ALL: .end sdivrem2
 
@@ -358,10 +354,10 @@ entry:
 
 ; udivrem2 is too complex to effectively check. We can at least check for the
 ; calls though.
-; ACC32:         lw $25, %call16(__umoddi3)(
-; ACC32:         jalr $25
 ; ACC32:         lw $25, %call16(__udivdi3)(
 ; ACC32:         jalr $25
+; ACC32:         mul
+; ACC32:         subu
 
 ; ACC64:         ddivu $zero, $4, $5
 ; ACC64-TRAP:    teq $5, $zero, 7
@@ -370,14 +366,12 @@ entry:
 ; ACC64:         mfhi $[[R0:[0-9]+]]
 ; ACC64:         sd $[[R0]], 0(${{[0-9]+}})
 
-; GPR64:         dmodu $[[R0:[0-9]+]], $4, $5
-; GPR64-TRAP:    teq $5, $zero, 7
-; NOCHECK-NOT:   teq
-; GPR64:         sd $[[R0]], 0(${{[0-9]+}})
-
-; GPR64-DAG:     ddivu $2, $4, $5
+; GPR64:         ddivu $[[R0:[0-9]+]], $4, $5
 ; GPR64-TRAP:    teq $5, $zero, 7
 ; NOCHECK-NOT:   teq
+; GPR64-DAG:     dmul $[[R1:[0-9]+]], $[[R0]], $5
+; GPR64-DAG:     dsubu $[[R2:[0-9]+]], $4, $[[R1]]
+; GPR64:         sd $[[R2]], 0(${{[0-9]+}})
 
 ; ALL: .end udivrem2
 
diff --git a/llvm/test/CodeGen/NVPTX/divrem-combine.ll b/llvm/test/CodeGen/NVPTX/divrem-combine.ll
index f67533fa73dc5..01fad9053cf2d 100644
--- a/llvm/test/CodeGen/NVPTX/divrem-combine.ll
+++ b/llvm/test/CodeGen/NVPTX/divrem-combine.ll
@@ -1,7 +1,5 @@
 ; RUN: llc -O2 < %s -mtriple=nvptx64 -mcpu=sm_35 | FileCheck %s --check-prefix=O2 --check-prefix=CHECK
-; RUN: llc -O0 < %s -mtriple=nvptx64 -mcpu=sm_35 | FileCheck %s --check-prefix=O0 --check-prefix=CHECK
 ; RUN: %if ptxas %{ llc -O2 < %s -mtriple=nvptx64 -mcpu=sm_35 | %ptxas-verify %}
-; RUN: %if ptxas %{ llc -O0 < %s -mtriple=nvptx64 -mcpu=sm_35 | %ptxas-verify %}
 
 ; The following IR
 ;
@@ -13,14 +11,13 @@
 ;   quot = n / d
 ;   rem = n - (n / d) * d
 ;
-; during NVPTX isel, at -O2.  At -O0, we should leave it alone.
+; during DAG combining (even at -O0)
 
 ; CHECK-LABEL: sdiv32(
 define void @sdiv32(i32 %n, i32 %d, ptr %quot_ret, ptr %rem_ret) {
   ; CHECK: div.s32 [[quot:%r[0-9]+]], [[num:%r[0-9]+]], [[den:%r[0-9]+]];
   %quot = sdiv i32 %n, %d
 
-  ; O0: rem.s32
   ; (This is unfortunately order-sensitive, even though mul is commutative.)
   ; O2: mul.lo.s32 [[mul:%r[0-9]+]], [[quot]], [[den]];
   ; O2: sub.s32 [[rem:%r[0-9]+]], [[num]], [[mul]]
@@ -38,8 +35,6 @@ define void @udiv32(i32 %n, i32 %d, ptr %quot_ret, ptr %rem_ret) {
   ; CHECK: div.u32 [[quot:%r[0-9]+]], [[num:%r[0-9]+]], [[den:%r[0-9]+]];
   %quot = udiv i32 %n, %d
 
-  ; O0: rem.u32
-
   ; Selection DAG doesn't know whether this is signed or unsigned
   ; multiplication and subtraction, but it doesn't make a difference either
   ; way.
diff --git a/llvm/test/CodeGen/PowerPC/p10-vector-modulo.ll b/llvm/test/CodeGen/PowerPC/p10-vector-modulo.ll
index 14fcf2460ef3d..292d4ea16cbc1 100644
--- a/llvm/test/CodeGen/PowerPC/p10-vector-modulo.ll
+++ b/llvm/test/CodeGen/PowerPC/p10-vector-modulo.ll
@@ -78,9 +78,10 @@ entry:
 define <2 x i64> @test_vmodud_with_div(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: test_vmodud_with_div:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vmodud v4, v2, v3
-; CHECK-NEXT:    vdivud v2, v2, v3
-; CHECK-NEXT:    vaddudm v2, v4, v2
+; CHECK-NEXT:    vdivud v4, v2, v3
+; CHECK-NEXT:    vmulld v3, v4, v3
+; CHECK-NEXT:    vsubudm v2, v2, v3
+; CHECK-NEXT:    vaddudm v2, v2, v4
 ; CHECK-NEXT:    blr
 entry:
   %rem = urem <2 x i64> %a, %b
@@ -92,9 +93,10 @@ entry:
 define <2 x i64> @test_vmodsd_with_div(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: test_vmodsd_with_div:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vmodsd v4, v2, v3
-; CHECK-NEXT:    vdivsd v2, v2, v3
-; CHECK-NEXT:    vaddudm v2, v4, v2
+; CHECK-NEXT:    vdivsd v4, v2, v3
+; CHECK-NEXT:    vmulld v3, v4, v3
+; CHECK-NEXT:    vsubudm v2, v2, v3
+; CHECK-NEXT:    vaddudm v2, v2, v4
 ; CHECK-NEXT:    blr
 entry:
   %rem = srem <2 x i64> %a, %b
@@ -106,9 +108,10 @@ entry:
 define <4 x i32> @test_vmoduw_with_div(<4 x i32> %a, <4 x i32> %b) {
 ; CHECK-LABEL: test_vmoduw_with_div:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vmoduw v4, v2, v3
-; CHECK-NEXT:    vdivuw v2, v2, v3
-; CHECK-NEXT:    vadduwm v2, v4, v2
+; CHECK-NEXT:    vdivuw v4, v2, v3
+; CHECK-NEXT:    vmuluwm v3, v4, v3
+; CHECK-NEXT:    vsubuwm v2, v2, v3
+; CHECK-NEXT:    vadduwm v2, v2, v4
 ; CHECK-NEXT:    blr
 entry:
   %rem = urem <4 x i32> %a, %b
@@ -120,9 +123,10 @@ entry:
 define <4 x i32> @test_vmodsw_div(<4 x i32> %a, <4 x i32> %b) {
 ; CHECK-LABEL: test_vmodsw_div:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vmodsw v4, v2, v3
-; CHECK-NEXT:    vdivsw v2, v2, v3
-; CHECK-NEXT:    vadduwm v2, v4, v2
+; CHECK-NEXT:    vdivsw v4, v2, v3
+; CHECK-NEXT:    vmuluwm v3, v4, v3
+; CHECK-NEXT:    vsubuwm v2, v2, v3
+; CHECK-NEXT:    vadduwm v2, v2, v4
 ; CHECK-NEXT:    blr
 entry:
   %rem = srem <4 x i32> %a, %b
diff --git a/llvm/test/CodeGen/PowerPC/ppc64-P9-mod.ll b/llvm/test/CodeGen/PowerPC/ppc64-P9-mod.ll
index 21a7b214e89cc..6d2f65e187351 100644
--- a/llvm/test/CodeGen/PowerPC/ppc64-P9-mod.ll
+++ b/llvm/test/CodeGen/PowerPC/ppc64-P9-mod.ll
@@ -88,7 +88,10 @@ entry:
   store i32 %div, ptr @div_resultsw, align 4
   ret void
 ; CHECK-LABEL: modulo_div_sw
-; CHECK: modsw {{[0-9]+}}, 3, 4
+; CHECK-NOT: modsw
+; CHECK: divw {{[0-9]+}}, 3, 4
+; CHECK: mullw
+; CHECK: sub
 ; CHECK: blr
 ; CHECK-DRP-LABEL: modulo_div_sw
 ; CHECK-DRP-NOT: modsw
@@ -132,7 +135,10 @@ entry:
   store i32 %div, ptr @div_resultuw, align 4
   ret void
 ; CHECK-LABEL: modulo_div_uw
-; CHECK: moduw {{[0-9]+}}, 3, 4
+; CHECK-NOT: moduw
+; CHECK: divwu {{[0-9]+}}, 3, 4
+; CHECK: mullw
+; CHECK: sub
 ; CHECK: blr
 ; CHECK-DRP-LABEL: modulo_div_uw
 ; CHECK-DRP-NOT: moduw
diff --git a/llvm/test/CodeGen/PowerPC/srem-vector-lkk.ll b/llvm/test/CodeGen/PowerPC/srem-vector-lkk.ll
index df55b92997765..7243e9842e343 100644
--- a/llvm/test/CodeGen/PowerPC/srem-vector-lkk.ll
+++ b/llvm/test/CodeGen/PowerPC/srem-vector-lkk.ll
@@ -465,125 +465,105 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) {
 ; P9LE:       # %bb.0:
 ; P9LE-NEXT:    li r3, 0
 ; P9LE-NEXT:    lis r4, -21386
-; P9LE-NEXT:    vextuhrx r3, r3, v2
+; P9LE-NEXT:    xxspltib v3, 95
 ; P9LE-NEXT:    ori r4, r4, 37253
+; P9LE-NEXT:    vextuhrx r3, r3, v2
+; P9LE-NEXT:    vxor v4, v4, v4
+; P9LE-NEXT:    vupklsb v3, v3
 ; P9LE-NEXT:    extsh r3, r3
 ; P9LE-NEXT:    mulhw r5, r3, r4
-; P9LE-NEXT:    add r5, r5, r3
-; P9LE-NEXT:    srwi r6, r5, 31
-; P9LE-NEXT:    srawi r5, r5, 6
-; P9LE-NEXT:    add r5, r5, r6
-; P9LE-NEXT:    mulli r6, r5, 95
-; P9LE-NEXT:    sub r3, r3, r6
-; P9LE-NEXT:    mtvsrd v3, r3
+; P9LE-NEXT:    add r3, r5, r3
+; P9LE-NEXT:    srwi r5, r3, 31
+; P9LE-NEXT:    srawi r3, r3, 6
+; P9LE-NEXT:    add r3, r3, r5
+; P9LE-NEXT:    mtvsrd v5, r3
 ; P9LE-NEXT:    li r3, 2
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    extsh r6, r3
-; P9LE-NEXT:    mulhw r7, r6, r4
-; P9LE-NEXT:    add r6, r7, r6
-; P9LE-NEXT:    srwi r7, r6, 31
-; P9LE-NEXT:    srawi r6, r6, 6
-; P9LE-NEXT:    add r6, r6, r7
-; P9LE-NEXT:    mulli r7, r6, 95
-; P9LE-NEXT:    sub r3, r3, r7
-; P9LE-NEXT:    mtvsrd v4, r3
+; P9LE-NEXT:    extsh r3, r3
+; P9LE-NEXT:    mulhw r5, r3, r4
+; P9LE-NEXT:    add r3, r5, r3
+; P9LE-NEXT:    srwi r5, r3, 31
+; P9LE-NEXT:    srwi r3, r3, 6
+; P9LE-NEXT:    add r3, r3, r5
+; P9LE-NEXT:    mtvsrd v0, r3
 ; P9LE-NEXT:    li r3, 4
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    vmrghh v3, v4, v3
-; P9LE-NEXT:    extsh r7, r3
-; P9LE-NEXT:    mulhw r8, r7, r4
-; P9LE-NEXT:    add r7, r8, r7
-; P9LE-NEXT:    srwi r8, r7, 31
-; P9LE-NEXT:    srawi r7, r7, 6
-; P9LE-NEXT:    add r7, r7, r8
-; P9LE-NEXT:    mulli r8, r7, 95
-; P9LE-NEXT:    sub r3, r3, r8
-; P9LE-NEXT:    mtvsrd v4, r3
+; P9LE-NEXT:    vmrghh v5, v0, v5
+; P9LE-NEXT:    extsh r3, r3
+; P9LE-NEXT:    mulhw r5, r3, r4
+; P9LE-NEXT:    add r3, r5, r3
+; P9LE-NEXT:    srwi r5, r3, 31
+; P9LE-NEXT:    srwi r3, r3, 6
+; P9LE-NEXT:    add r3, r3, r5
+; P9LE-NEXT:    mtvsrd v0, r3
 ; P9LE-NEXT:    li r3, 6
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    extsh r8, r3
-; P9LE-NEXT:    mulhw r4, r8, r4
-; P9LE-NEXT:    add r4, r4, r8
-; P9LE-NEXT:    srwi r8, r4, 31
-; P9LE-NEXT:    srawi r4, r4, 6
-; P9LE-NEXT:    add r4, r4, r8
-; P9LE-NEXT:    mulli r8, r4, 95
-; P9LE-NEXT:    mtvsrd v5, r4
-; P9LE-NEXT:    sub r3, r3, r8
-; P9LE-NEXT:    mtvsrd v2, r3
-; P9LE-NEXT:    vmrghh v2, v2, v4
-; P9LE-NEXT:    mtvsrd v4, r6
-; P9LE-NEXT:    xxmrglw v2, v2, v3
-; P9LE-NEXT:    mtvsrd v3, r5
-; P9LE-NEXT:    vmrghh v3, v4, v3
-; P9LE-NEXT:    mtvsrd v4, r7
-; P9LE-NEXT:    vmrghh v4, v5, v4
-; P9LE-NEXT:    xxmrglw v3, v4, v3
-; P9LE-NEXT:    vadduhm v2, v2, v3
+; P9LE-NEXT:    extsh r3, r3
+; P9LE-NEXT:    mulhw r4, r3, r4
+; P9LE-NEXT:    add r3, r4, r3
+; P9LE-NEXT:    srwi r4, r3, 31
+; P9LE-NEXT:    srwi r3, r3, 6
+; P9LE-NEXT:    add r3, r3, r4
+; P9LE-NEXT:    mtvsrd v1, r3
+; P9LE-NEXT:    vmrghh v0, v1, v0
+; P9LE-NEXT:    xxmrglw v5, v0, v5
+; P9LE-NEXT:    vmladduhm v3, v5, v3, v4
+; P9LE-NEXT:    vsubuhm v2, v2, v3
+; P9LE-NEXT:    vadduhm v2, v2, v5
 ; P9LE-NEXT:    blr
 ;
 ; P9BE-LABEL: combine_srem_sdiv:
 ; P9BE:       # %bb.0:
 ; P9BE-NEXT:    li r3, 6
-; P9BE-NEXT:    lis r5, -21386
+; P9BE-NEXT:    lis r4, -21386
+; P9BE-NEXT:    xxspltib v3, 95
+; P9BE-NEXT:    ori r4, r4, 37253
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    ori r5, r5, 37253
-; P9BE-NEXT:    extsh r4, r3
-; P9BE-NEXT:    mulhw r6, r4, r5
-; P9BE-NEXT:    add r4, r6, r4
-; P9BE-NEXT:    srwi r6, r4, 31
-; P9BE-NEXT:    srawi r4, r4, 6
-; P9BE-NEXT:    add r4, r4, r6
-; P9BE-NEXT:    mulli r6, r4, 95
-; P9BE-NEXT:    sub r3, r3, r6
+; P9BE-NEXT:    vxor v4, v4, v4
+; P9BE-NEXT:    vupklsb v3, v3
+; P9BE-NEXT:    extsh r3, r3
+; P9BE-NEXT:    mulhw r5, r3, r4
+; P9BE-NEXT:    add r3, r5, r3
+; P9BE-NEXT:    srwi r5, r3, 31
+; P9BE-NEXT:    srwi r3, r3, 6
+; P9BE-NEXT:    add r3, r3, r5
 ; P9BE-NEXT:    mtfprwz f0, r3
 ; P9BE-NEXT:    li r3, 4
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    extsh r6, r3
-; P9BE-NEXT:    mulhw r7, r6, r5
-; P9BE-NEXT:    add r6, r7, r6
-; P9BE-NEXT:    srwi r7, r6, 31
-; P9BE-NEXT:    srawi r6, r6, 6
-; P9BE-NEXT:    add r6, r6, r7
-; P9BE-NEXT:    mulli r7, r6, 95
-; P9BE-NEXT:    sub r3, r3, r7
+; P9BE-NEXT:    extsh r3, r3
+; P9BE-NEXT:    mulhw r5, r3, r4
+; P9BE-NEXT:    add r3, r5, r3
+; P9BE-NEXT:    srwi r5, r3, 31
+; P9BE-NEXT:    srwi r3, r3, 6
+; P9BE-NEXT:    add r3, r3, r5
 ; P9BE-NEXT:    mtfprwz f1, r3
 ; P9BE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
 ; P9BE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
 ; P9BE-NEXT:    lxv vs2, 0(r3)
 ; P9BE-NEXT:    li r3, 2
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    extsh r7, r3
+; P9BE-NEXT:    extsh r3, r3
 ; P9BE-NEXT:    xxperm vs0, vs1, vs2
-; P9BE-NEXT:    mulhw r8, r7, r5
-; P9BE-NEXT:    add r7, r8, r7
-; P9BE-NEXT:    srwi r8, r7, 31
-; P9BE-NEXT:    srawi r7, r7, 6
-; P9BE-NEXT:    add r7, r7, r8
-; P9BE-NEXT:    mulli r8, r7, 95
-; P9BE-NEXT:    sub r3, r3, r8
+; P9BE-NEXT:    mulhw r5, r3, r4
+; P9BE-NEXT:    add r3, r5, r3
+; P9BE-NEXT:    srwi r5, r3, 31
+; P9BE-NEXT:    srwi r3, r3, 6
+; P9BE-NEXT:    add r3, r3, r5
 ; P9BE-NEXT:    mtfprwz f1, r3
 ; P9BE-NEXT:    li r3, 0
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
 ; P9BE-NEXT:    extsh r3, r3
-; P9BE-NEXT:    mulhw r5, r3, r5
-; P9BE-NEXT:    add r5, r5, r3
-; P9BE-NEXT:    srwi r8, r5, 31
-; P9BE-NEXT:    srawi r5, r5, 6
-; P9BE-NEXT:    add r5, r5, r8
-; P9BE-NEXT:    mulli r8, r5, 95
-; P9BE-NEXT:    sub r3, r3, r8
+; P9BE-NEXT:    mulhw r4, r3, r4
+; P9BE-NEXT:    add r3, r4, r3
+; P9BE-NEXT:    srwi r4, r3, 31
+; P9BE-NEXT:    srawi r3, r3, 6
+; P9BE-NEXT:    add r3, r3, r4
 ; P9BE-NEXT:    mtfprwz f3, r3
 ; P9BE-NEXT:    xxperm vs1, vs3, vs2
-; P9BE-NEXT:    mtfprwz f3, r5
-; P9BE-NEXT:    xxmrghw v2, vs1, vs0
-; P9BE-NEXT:    mtfprwz f0, r4
-; P9BE-NEXT:    mtfprwz f1, r6
-; P9BE-NEXT:    xxperm vs0, vs1, vs2
-; P9BE-NEXT:    mtfprwz f1, r7
-; P9BE-NEXT:    xxperm vs1, vs3, vs2
-; P9BE-NEXT:    xxmrghw v3, vs1, vs0
-; P9BE-NEXT:    vadduhm v2, v2, v3
+; P9BE-NEXT:    xxmrghw v5, vs1, vs0
+; P9BE-NEXT:    vmladduhm v3, v5, v3, v4
+; P9BE-NEXT:    vsubuhm v2, v2, v3
+; P9BE-NEXT:    vadduhm v2, v2, v5
 ; P9BE-NEXT:    blr
 ;
 ; P8LE-LABEL: combine_srem_sdiv:
@@ -592,118 +572,101 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) {
 ; P8LE-NEXT:    lis r4, -21386
 ; P8LE-NEXT:    mffprd r3, f0
 ; P8LE-NEXT:    ori r4, r4, 37253
+; P8LE-NEXT:    clrldi r5, r3, 48
 ; P8LE-NEXT:    rldicl r6, r3, 48, 48
 ; P8LE-NEXT:    rldicl r7, r3, 32, 48
-; P8LE-NEXT:    clrldi r5, r3, 48
 ; P8LE-NEXT:    rldicl r3, r3, 16, 48
-; P8LE-NEXT:    extsh r8, r6
-; P8LE-NEXT:    extsh r9, r7
 ; P8LE-NEXT:    extsh r5, r5
-; P8LE-NEXT:    extsh r10, r3
-; P8LE-NEXT:    mulhw r11, r8, r4
-; P8LE-NEXT:    add r8, r11, r8
-; P8LE-NEXT:    mulhw r11, r9, r4
-; P8LE-NEXT:    add r9, r11, r9
-; P8LE-NEXT:    mulhw r11, r5, r4
-; P8LE-NEXT:    mulhw r4, r10, r4
-; P8LE-NEXT:    add r11, r11, r5
-; P8LE-NEXT:    add r4, r4, r10
-; P8LE-NEXT:    srwi r10, r11, 31
-; P8LE-NEXT:    srawi r11, r11, 6
-; P8LE-NEXT:    add r10, r11, r10
-; P8LE-NEXT:    srwi r11, r8, 31
-; P8LE-NEXT:    srawi r8, r8, 6
-; P8LE-NEXT:    add r8, r8, r11
-; P8LE-NEXT:    srwi r11, r9, 31
-; P8LE-NEXT:    srawi r9, r9, 6
-; P8LE-NEXT:    mtvsrd v2, r10
-; P8LE-NEXT:    add r9, r9, r11
-; P8LE-NEXT:    srwi r11, r4, 31
-; P8LE-NEXT:    srawi r4, r4, 6
-; P8LE-NEXT:    mtvsrd v3, r8
-; P8LE-NEXT:    add r4, r4, r11
-; P8LE-NEXT:    mulli r11, r10, 95
-; P8LE-NEXT:    sub r5, r5, r11
-; P8LE-NEXT:    mulli r11, r8, 95
+; P8LE-NEXT:    extsh r6, r6
+; P8LE-NEXT:    extsh r7, r7
+; P8LE-NEXT:    extsh r3, r3
+; P8LE-NEXT:    mulhw r8, r5, r4
+; P8LE-NEXT:    add r5, r8, r5
+; P8LE-NEXT:    mulhw r8, r6, r4
+; P8LE-NEXT:    add r6, r8, r6
+; P8LE-NEXT:    mulhw r8, r7, r4
+; P8LE-NEXT:    mulhw r4, r3, r4
+; P8LE-NEXT:    add r3, r4, r3
+; P8LE-NEXT:    srwi r4, r5, 31
+; P8LE-NEXT:    srawi r5, r5, 6
+; P8LE-NEXT:    add r7, r8, r7
+; P8LE-NEXT:    add r4, r5, r4
+; P8LE-NEXT:    srwi r5, r6, 31
+; P8LE-NEXT:    srwi r6, r6, 6
+; P8LE-NEXT:    add r5, r6, r5
+; P8LE-NEXT:    mtvsrd v3, r4
+; P8LE-NEXT:    srwi r4, r3, 31
+; P8LE-NEXT:    srwi r3, r3, 6
+; P8LE-NEXT:    srwi r6, r7, 31
+; P8LE-NEXT:    srwi r7, r7, 6
 ; P8LE-NEXT:    mtvsrd v4, r5
-; P8LE-NEXT:    sub r6, r6, r11
-; P8LE-NEXT:    mulli r11, r9, 95
+; P8LE-NEXT:    add r3, r3, r4
+; P8LE-NEXT:    add r6, r7, r6
 ; P8LE-NEXT:    mtvsrd v5, r6
-; P8LE-NEXT:    sub r7, r7, r11
-; P8LE-NEXT:    mulli r11, r4, 95
-; P8LE-NEXT:    mtvsrd v0, r7
-; P8LE-NEXT:    sub r3, r3, r11
-; P8LE-NEXT:    vmrghh v2, v3, v2
-; P8LE-NEXT:    mtvsrd v3, r9
-; P8LE-NEXT:    vmrghh v4, v5, v4
-; P8LE-NEXT:    mtvsrd v5, r3
-; P8LE-NEXT:    vmrghh v5, v5, v0
-; P8LE-NEXT:    mtvsrd v0, r4
-; P8LE-NEXT:    xxmrglw v4, v5, v4
-; P8LE-NEXT:    vmrghh v3, v0, v3
-; P8LE-NEXT:    xxmrglw v2, v3, v2
-; P8LE-NEXT:    vadduhm v2, v4, v2
+; P8LE-NEXT:    vmrghh v3, v4, v3
+; P8LE-NEXT:    mtvsrd v4, r3
+; P8LE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
+; P8LE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
+; P8LE-NEXT:    lxvd2x vs0, 0, r3
+; P8LE-NEXT:    vmrghh v4, v4, v5
+; P8LE-NEXT:    xxmrglw v3, v4, v3
+; P8LE-NEXT:    vxor v4, v4, v4
+; P8LE-NEXT:    xxswapd v5, vs0
+; P8LE-NEXT:    vmladduhm v4, v3, v5, v4
+; P8LE-NEXT:    vsubuhm v2, v2, v4
+; P8LE-NEXT:    vadduhm v2, v2, v3
 ; P8LE-NEXT:    blr
 ;
 ; P8BE-LABEL: combine_srem_sdiv:
 ; P8BE:       # %bb.0:
-; P8BE-NEXT:    mfvsrd r4, v2
-; P8BE-NEXT:    lis r5, -21386
-; P8BE-NEXT:    ori r5, r5, 37253
-; P8BE-NEXT:    clrldi r3, r4, 48
-; P8BE-NEXT:    rldicl r6, r4, 48, 48
-; P8BE-NEXT:    rldicl r7, r4, 32, 48
-; P8BE-NEXT:    rldicl r4, r4, 16, 48
-; P8BE-NEXT:    extsh r8, r3
-; P8BE-NEXT:    extsh r9, r6
-; P8BE-NEXT:    extsh r10, r7
-; P8BE-NEXT:    extsh r4, r4
-; P8BE-NEXT:    mulhw r11, r8, r5
-; P8BE-NEXT:    add r8, r11, r8
-; P8BE-NEXT:    mulhw r11, r9, r5
-; P8BE-NEXT:    add r9, r11, r9
-; P8BE-NEXT:    mulhw r11, r10, r5
-; P8BE-NEXT:    mulhw r5, r4, r5
-; P8BE-NEXT:    add r10, r11, r10
-; P8BE-NEXT:    srwi r11, r8, 31
-; P8BE-NEXT:    srawi r8, r8, 6
-; P8BE-NEXT:    add r5, r5, r4
-; P8BE-NEXT:    add r8, r8, r11
-; P8BE-NEXT:    srwi r11, r9, 31
-; P8BE-NEXT:    srawi r9, r9, 6
-; P8BE-NEXT:    add r9, r9, r11
-; P8BE-NEXT:    srwi r11, r10, 31
-; P8BE-NEXT:    srawi r10, r10, 6
-; P8BE-NEXT:    mtvsrwz v3, r8
-; P8BE-NEXT:    add r10, r10, r11
-; P8BE-NEXT:    srwi r11, r5, 31
-; P8BE-NEXT:    srawi r5, r5, 6
-; P8BE-NEXT:    mtvsrwz v4, r9
-; P8BE-NEXT:    add r5, r5, r11
-; P8BE-NEXT:    mulli r11, r8, 95
-; P8BE-NEXT:    sub r3, r3, r11
-; P8BE-NEXT:    mulli r11, r9, 95
-; P8BE-NEXT:    mtvsrwz v5, r3
-; P8BE-NEXT:    sub r6, r6, r11
-; P8BE-NEXT:    mulli r11, r10, 95
+; P8BE-NEXT:    mfvsrd r3, v2
+; P8BE-NEXT:    lis r4, -21386
+; P8BE-NEXT:    ori r4, r4, 37253
+; P8BE-NEXT:    clrldi r5, r3, 48
+; P8BE-NEXT:    rldicl r6, r3, 48, 48
+; P8BE-NEXT:    rldicl r7, r3, 32, 48
+; P8BE-NEXT:    rldicl r3, r3, 16, 48
+; P8BE-NEXT:    extsh r5, r5
+; P8BE-NEXT:    extsh r6, r6
+; P8BE-NEXT:    extsh r7, r7
+; P8BE-NEXT:    extsh r3, r3
+; P8BE-NEXT:    mulhw r8, r5, r4
+; P8BE-NEXT:    add r5, r8, r5
+; P8BE-NEXT:    mulhw r8, r6, r4
+; P8BE-NEXT:    add r6, r8, r6
+; P8BE-NEXT:    mulhw r8, r7, r4
+; P8BE-NEXT:    mulhw r4, r3, r4
+; P8BE-NEXT:    add r3, r4, r3
+; P8BE-NEXT:    addis r4, r2, .LCPI2_1 at toc@ha
+; P8BE-NEXT:    add r7, r8, r7
+; P8BE-NEXT:    addi r4, r4, .LCPI2_1 at toc@l
+; P8BE-NEXT:    lxvw4x v3, 0, r4
+; P8BE-NEXT:    srwi r4, r5, 31
+; P8BE-NEXT:    srwi r5, r5, 6
+; P8BE-NEXT:    add r4, r5, r4
+; P8BE-NEXT:    srwi r5, r6, 31
+; P8BE-NEXT:    srwi r6, r6, 6
+; P8BE-NEXT:    add r5, r6, r5
+; P8BE-NEXT:    mtvsrwz v4, r4
+; P8BE-NEXT:    srwi r6, r7, 31
+; P8BE-NEXT:    srwi r7, r7, 6
+; P8BE-NEXT:    srwi r4, r3, 31
+; P8BE-NEXT:    srawi r3, r3, 6
+; P8BE-NEXT:    mtvsrwz v5, r5
+; P8BE-NEXT:    add r6, r7, r6
+; P8BE-NEXT:    add r3, r3, r4
 ; P8BE-NEXT:    mtvsrwz v0, r6
-; P8BE-NEXT:    sub r7, r7, r11
-; P8BE-NEXT:    mulli r11, r5, 95
-; P8BE-NEXT:    mtvsrwz v1, r7
-; P8BE-NEXT:    sub r4, r4, r11
-; P8BE-NEXT:    addis r11, r2, .LCPI2_0 at toc@ha
-; P8BE-NEXT:    addi r11, r11, .LCPI2_0 at toc@l
-; P8BE-NEXT:    lxvw4x v2, 0, r11
-; P8BE-NEXT:    vperm v5, v0, v5, v2
-; P8BE-NEXT:    mtvsrwz v0, r4
-; P8BE-NEXT:    vperm v3, v4, v3, v2
-; P8BE-NEXT:    mtvsrwz v4, r10
-; P8BE-NEXT:    vperm v0, v0, v1, v2
-; P8BE-NEXT:    mtvsrwz v1, r5
-; P8BE-NEXT:    vperm v2, v1, v4, v2
-; P8BE-NEXT:    xxmrghw v4, v0, v5
-; P8BE-NEXT:    xxmrghw v2, v2, v3
-; P8BE-NEXT:    vadduhm v2, v4, v2
+; P8BE-NEXT:    vperm v4, v5, v4, v3
+; P8BE-NEXT:    mtvsrwz v5, r3
+; P8BE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
+; P8BE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
+; P8BE-NEXT:    vperm v3, v5, v0, v3
+; P8BE-NEXT:    vxor v5, v5, v5
+; P8BE-NEXT:    xxmrghw v3, v3, v4
+; P8BE-NEXT:    lxvw4x v4, 0, r3
+; P8BE-NEXT:    vmladduhm v4, v3, v4, v5
+; P8BE-NEXT:    vsubuhm v2, v2, v4
+; P8BE-NEXT:    vadduhm v2, v2, v3
 ; P8BE-NEXT:    blr
   %1 = srem <4 x i16> %x, <i16 95, i16 95, i16 95, i16 95>
   %2 = sdiv <4 x i16> %x, <i16 95, i16 95, i16 95, i16 95>
diff --git a/llvm/test/CodeGen/PowerPC/urem-vector-lkk.ll b/llvm/test/CodeGen/PowerPC/urem-vector-lkk.ll
index 98314a02c23fe..c07e500ec5a03 100644
--- a/llvm/test/CodeGen/PowerPC/urem-vector-lkk.ll
+++ b/llvm/test/CodeGen/PowerPC/urem-vector-lkk.ll
@@ -345,93 +345,73 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) {
 ; P9LE:       # %bb.0:
 ; P9LE-NEXT:    li r3, 0
 ; P9LE-NEXT:    lis r4, 689
-; P9LE-NEXT:    vextuhrx r3, r3, v2
+; P9LE-NEXT:    xxspltib v3, 95
 ; P9LE-NEXT:    ori r4, r4, 55879
+; P9LE-NEXT:    vextuhrx r3, r3, v2
+; P9LE-NEXT:    vxor v4, v4, v4
+; P9LE-NEXT:    vupklsb v3, v3
 ; P9LE-NEXT:    clrlwi r3, r3, 16
-; P9LE-NEXT:    mulhwu r5, r3, r4
-; P9LE-NEXT:    mulli r6, r5, 95
-; P9LE-NEXT:    sub r3, r3, r6
-; P9LE-NEXT:    mtvsrd v3, r3
+; P9LE-NEXT:    mulhwu r3, r3, r4
+; P9LE-NEXT:    mtvsrd v5, r3
 ; P9LE-NEXT:    li r3, 2
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    clrlwi r6, r3, 16
-; P9LE-NEXT:    mulhwu r6, r6, r4
-; P9LE-NEXT:    mulli r7, r6, 95
-; P9LE-NEXT:    sub r3, r3, r7
-; P9LE-NEXT:    mtvsrd v4, r3
+; P9LE-NEXT:    clrlwi r3, r3, 16
+; P9LE-NEXT:    mulhwu r3, r3, r4
+; P9LE-NEXT:    mtvsrd v0, r3
 ; P9LE-NEXT:    li r3, 4
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    vmrghh v3, v4, v3
-; P9LE-NEXT:    clrlwi r7, r3, 16
-; P9LE-NEXT:    mulhwu r7, r7, r4
-; P9LE-NEXT:    mulli r8, r7, 95
-; P9LE-NEXT:    sub r3, r3, r8
-; P9LE-NEXT:    mtvsrd v4, r3
+; P9LE-NEXT:    vmrghh v5, v0, v5
+; P9LE-NEXT:    clrlwi r3, r3, 16
+; P9LE-NEXT:    mulhwu r3, r3, r4
+; P9LE-NEXT:    mtvsrd v0, r3
 ; P9LE-NEXT:    li r3, 6
 ; P9LE-NEXT:    vextuhrx r3, r3, v2
-; P9LE-NEXT:    clrlwi r8, r3, 16
-; P9LE-NEXT:    mulhwu r4, r8, r4
-; P9LE-NEXT:    mulli r8, r4, 95
-; P9LE-NEXT:    mtvsrd v5, r4
-; P9LE-NEXT:    sub r3, r3, r8
-; P9LE-NEXT:    mtvsrd v2, r3
-; P9LE-NEXT:    vmrghh v2, v2, v4
-; P9LE-NEXT:    mtvsrd v4, r6
-; P9LE-NEXT:    xxmrglw v2, v2, v3
-; P9LE-NEXT:    mtvsrd v3, r5
-; P9LE-NEXT:    vmrghh v3, v4, v3
-; P9LE-NEXT:    mtvsrd v4, r7
-; P9LE-NEXT:    vmrghh v4, v5, v4
-; P9LE-NEXT:    xxmrglw v3, v4, v3
-; P9LE-NEXT:    vadduhm v2, v2, v3
+; P9LE-NEXT:    clrlwi r3, r3, 16
+; P9LE-NEXT:    mulhwu r3, r3, r4
+; P9LE-NEXT:    mtvsrd v1, r3
+; P9LE-NEXT:    vmrghh v0, v1, v0
+; P9LE-NEXT:    xxmrglw v5, v0, v5
+; P9LE-NEXT:    vmladduhm v3, v5, v3, v4
+; P9LE-NEXT:    vsubuhm v2, v2, v3
+; P9LE-NEXT:    vadduhm v2, v2, v5
 ; P9LE-NEXT:    blr
 ;
 ; P9BE-LABEL: combine_urem_udiv:
 ; P9BE:       # %bb.0:
 ; P9BE-NEXT:    li r3, 6
-; P9BE-NEXT:    lis r5, 689
+; P9BE-NEXT:    lis r4, 689
+; P9BE-NEXT:    xxspltib v3, 95
+; P9BE-NEXT:    ori r4, r4, 55879
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    ori r5, r5, 55879
-; P9BE-NEXT:    clrlwi r4, r3, 16
-; P9BE-NEXT:    mulhwu r4, r4, r5
-; P9BE-NEXT:    mulli r6, r4, 95
-; P9BE-NEXT:    sub r3, r3, r6
+; P9BE-NEXT:    vxor v4, v4, v4
+; P9BE-NEXT:    vupklsb v3, v3
+; P9BE-NEXT:    clrlwi r3, r3, 16
+; P9BE-NEXT:    mulhwu r3, r3, r4
 ; P9BE-NEXT:    mtfprwz f0, r3
 ; P9BE-NEXT:    li r3, 4
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    clrlwi r6, r3, 16
-; P9BE-NEXT:    mulhwu r6, r6, r5
-; P9BE-NEXT:    mulli r7, r6, 95
-; P9BE-NEXT:    sub r3, r3, r7
+; P9BE-NEXT:    clrlwi r3, r3, 16
+; P9BE-NEXT:    mulhwu r3, r3, r4
 ; P9BE-NEXT:    mtfprwz f1, r3
 ; P9BE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
 ; P9BE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
 ; P9BE-NEXT:    lxv vs2, 0(r3)
 ; P9BE-NEXT:    li r3, 2
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
-; P9BE-NEXT:    clrlwi r7, r3, 16
+; P9BE-NEXT:    clrlwi r3, r3, 16
 ; P9BE-NEXT:    xxperm vs0, vs1, vs2
-; P9BE-NEXT:    mulhwu r7, r7, r5
-; P9BE-NEXT:    mulli r8, r7, 95
-; P9BE-NEXT:    sub r3, r3, r8
+; P9BE-NEXT:    mulhwu r3, r3, r4
 ; P9BE-NEXT:    mtfprwz f1, r3
 ; P9BE-NEXT:    li r3, 0
 ; P9BE-NEXT:    vextuhlx r3, r3, v2
 ; P9BE-NEXT:    clrlwi r3, r3, 16
-; P9BE-NEXT:    mulhwu r5, r3, r5
-; P9BE-NEXT:    mulli r8, r5, 95
-; P9BE-NEXT:    sub r3, r3, r8
+; P9BE-NEXT:    mulhwu r3, r3, r4
 ; P9BE-NEXT:    mtfprwz f3, r3
 ; P9BE-NEXT:    xxperm vs1, vs3, vs2
-; P9BE-NEXT:    mtfprwz f3, r5
-; P9BE-NEXT:    xxmrghw v2, vs1, vs0
-; P9BE-NEXT:    mtfprwz f0, r4
-; P9BE-NEXT:    mtfprwz f1, r6
-; P9BE-NEXT:    xxperm vs0, vs1, vs2
-; P9BE-NEXT:    mtfprwz f1, r7
-; P9BE-NEXT:    xxperm vs1, vs3, vs2
-; P9BE-NEXT:    xxmrghw v3, vs1, vs0
-; P9BE-NEXT:    vadduhm v2, v2, v3
+; P9BE-NEXT:    xxmrghw v5, vs1, vs0
+; P9BE-NEXT:    vmladduhm v3, v5, v3, v4
+; P9BE-NEXT:    vsubuhm v2, v2, v3
+; P9BE-NEXT:    vadduhm v2, v2, v5
 ; P9BE-NEXT:    blr
 ;
 ; P8LE-LABEL: combine_urem_udiv:
@@ -441,85 +421,68 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) {
 ; P8LE-NEXT:    mffprd r3, f0
 ; P8LE-NEXT:    ori r4, r4, 55879
 ; P8LE-NEXT:    clrldi r5, r3, 48
-; P8LE-NEXT:    rldicl r6, r3, 48, 48
-; P8LE-NEXT:    rldicl r7, r3, 32, 48
-; P8LE-NEXT:    rldicl r3, r3, 16, 48
 ; P8LE-NEXT:    clrlwi r5, r5, 16
-; P8LE-NEXT:    clrlwi r8, r6, 16
-; P8LE-NEXT:    clrlwi r9, r7, 16
-; P8LE-NEXT:    clrlwi r10, r3, 16
-; P8LE-NEXT:    mulhwu r11, r5, r4
-; P8LE-NEXT:    mulhwu r8, r8, r4
-; P8LE-NEXT:    mulhwu r9, r9, r4
-; P8LE-NEXT:    mulhwu r4, r10, r4
-; P8LE-NEXT:    mulli r10, r11, 95
-; P8LE-NEXT:    mtvsrd v2, r11
-; P8LE-NEXT:    mtvsrd v3, r8
-; P8LE-NEXT:    sub r5, r5, r10
-; P8LE-NEXT:    mulli r10, r8, 95
+; P8LE-NEXT:    mulhwu r5, r5, r4
+; P8LE-NEXT:    mtvsrd v3, r5
+; P8LE-NEXT:    rldicl r5, r3, 48, 48
+; P8LE-NEXT:    clrlwi r5, r5, 16
+; P8LE-NEXT:    mulhwu r5, r5, r4
 ; P8LE-NEXT:    mtvsrd v4, r5
-; P8LE-NEXT:    sub r6, r6, r10
-; P8LE-NEXT:    mulli r10, r9, 95
-; P8LE-NEXT:    mtvsrd v5, r6
-; P8LE-NEXT:    sub r7, r7, r10
-; P8LE-NEXT:    mulli r10, r4, 95
-; P8LE-NEXT:    mtvsrd v0, r7
-; P8LE-NEXT:    sub r3, r3, r10
-; P8LE-NEXT:    vmrghh v2, v3, v2
-; P8LE-NEXT:    mtvsrd v3, r9
-; P8LE-NEXT:    vmrghh v4, v5, v4
-; P8LE-NEXT:    mtvsrd v5, r3
-; P8LE-NEXT:    vmrghh v5, v5, v0
-; P8LE-NEXT:    mtvsrd v0, r4
-; P8LE-NEXT:    xxmrglw v4, v5, v4
-; P8LE-NEXT:    vmrghh v3, v0, v3
-; P8LE-NEXT:    xxmrglw v2, v3, v2
-; P8LE-NEXT:    vadduhm v2, v4, v2
+; P8LE-NEXT:    rldicl r5, r3, 32, 48
+; P8LE-NEXT:    rldicl r3, r3, 16, 48
+; P8LE-NEXT:    clrlwi r3, r3, 16
+; P8LE-NEXT:    clrlwi r5, r5, 16
+; P8LE-NEXT:    mulhwu r3, r3, r4
+; P8LE-NEXT:    mulhwu r5, r5, r4
+; P8LE-NEXT:    mtvsrd v5, r5
+; P8LE-NEXT:    vmrghh v3, v4, v3
+; P8LE-NEXT:    mtvsrd v4, r3
+; P8LE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
+; P8LE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
+; P8LE-NEXT:    lxvd2x vs0, 0, r3
+; P8LE-NEXT:    vmrghh v4, v4, v5
+; P8LE-NEXT:    xxmrglw v3, v4, v3
+; P8LE-NEXT:    vxor v4, v4, v4
+; P8LE-NEXT:    xxswapd v5, vs0
+; P8LE-NEXT:    vmladduhm v4, v3, v5, v4
+; P8LE-NEXT:    vsubuhm v2, v2, v4
+; P8LE-NEXT:    vadduhm v2, v2, v3
 ; P8LE-NEXT:    blr
 ;
 ; P8BE-LABEL: combine_urem_udiv:
 ; P8BE:       # %bb.0:
 ; P8BE-NEXT:    mfvsrd r3, v2
+; P8BE-NEXT:    addis r5, r2, .LCPI2_1 at toc@ha
 ; P8BE-NEXT:    lis r4, 689
+; P8BE-NEXT:    addi r5, r5, .LCPI2_1 at toc@l
 ; P8BE-NEXT:    ori r4, r4, 55879
+; P8BE-NEXT:    lxvw4x v3, 0, r5
 ; P8BE-NEXT:    clrldi r5, r3, 48
-; P8BE-NEXT:    rldicl r6, r3, 48, 48
-; P8BE-NEXT:    rldicl r7, r3, 32, 48
+; P8BE-NEXT:    clrlwi r5, r5, 16
+; P8BE-NEXT:    mulhwu r5, r5, r4
+; P8BE-NEXT:    mtvsrwz v4, r5
+; P8BE-NEXT:    rldicl r5, r3, 48, 48
+; P8BE-NEXT:    clrlwi r5, r5, 16
+; P8BE-NEXT:    mulhwu r5, r5, r4
+; P8BE-NEXT:    mtvsrwz v5, r5
+; P8BE-NEXT:    rldicl r5, r3, 32, 48
 ; P8BE-NEXT:    rldicl r3, r3, 16, 48
-; P8BE-NEXT:    clrlwi r8, r5, 16
-; P8BE-NEXT:    clrlwi r9, r6, 16
-; P8BE-NEXT:    clrlwi r10, r7, 16
+; P8BE-NEXT:    clrlwi r5, r5, 16
 ; P8BE-NEXT:    clrlwi r3, r3, 16
-; P8BE-NEXT:    mulhwu r8, r8, r4
-; P8BE-NEXT:    mulhwu r9, r9, r4
-; P8BE-NEXT:    mulhwu r10, r10, r4
-; P8BE-NEXT:    mulhwu r4, r3, r4
-; P8BE-NEXT:    mulli r11, r8, 95
-; P8BE-NEXT:    mtvsrwz v3, r8
-; P8BE-NEXT:    mtvsrwz v4, r9
-; P8BE-NEXT:    sub r5, r5, r11
-; P8BE-NEXT:    mulli r11, r9, 95
-; P8BE-NEXT:    mtvsrwz v5, r5
-; P8BE-NEXT:    sub r6, r6, r11
-; P8BE-NEXT:    mulli r11, r10, 95
-; P8BE-NEXT:    mtvsrwz v0, r6
-; P8BE-NEXT:    sub r7, r7, r11
-; P8BE-NEXT:    mulli r11, r4, 95
-; P8BE-NEXT:    mtvsrwz v1, r7
-; P8BE-NEXT:    sub r3, r3, r11
-; P8BE-NEXT:    addis r11, r2, .LCPI2_0 at toc@ha
-; P8BE-NEXT:    addi r11, r11, .LCPI2_0 at toc@l
-; P8BE-NEXT:    lxvw4x v2, 0, r11
-; P8BE-NEXT:    vperm v5, v0, v5, v2
-; P8BE-NEXT:    mtvsrwz v0, r3
-; P8BE-NEXT:    vperm v3, v4, v3, v2
-; P8BE-NEXT:    mtvsrwz v4, r10
-; P8BE-NEXT:    vperm v0, v0, v1, v2
-; P8BE-NEXT:    mtvsrwz v1, r4
-; P8BE-NEXT:    vperm v2, v1, v4, v2
-; P8BE-NEXT:    xxmrghw v4, v0, v5
-; P8BE-NEXT:    xxmrghw v2, v2, v3
-; P8BE-NEXT:    vadduhm v2, v4, v2
+; P8BE-NEXT:    mulhwu r5, r5, r4
+; P8BE-NEXT:    mulhwu r3, r3, r4
+; P8BE-NEXT:    mtvsrwz v0, r5
+; P8BE-NEXT:    vperm v4, v5, v4, v3
+; P8BE-NEXT:    mtvsrwz v5, r3
+; P8BE-NEXT:    addis r3, r2, .LCPI2_0 at toc@ha
+; P8BE-NEXT:    addi r3, r3, .LCPI2_0 at toc@l
+; P8BE-NEXT:    vperm v3, v5, v0, v3
+; P8BE-NEXT:    vxor v5, v5, v5
+; P8BE-NEXT:    xxmrghw v3, v3, v4
+; P8BE-NEXT:    lxvw4x v4, 0, r3
+; P8BE-NEXT:    vmladduhm v4, v3, v4, v5
+; P8BE-NEXT:    vsubuhm v2, v2, v4
+; P8BE-NEXT:    vadduhm v2, v2, v3
 ; P8BE-NEXT:    blr
   %1 = urem <4 x i16> %x, <i16 95, i16 95, i16 95, i16 95>
   %2 = udiv <4 x i16> %x, <i16 95, i16 95, i16 95, i16 95>
diff --git a/llvm/test/CodeGen/RISCV/srem-lkk.ll b/llvm/test/CodeGen/RISCV/srem-lkk.ll
index b6e7684695aef..976f231cae36b 100644
--- a/llvm/test/CodeGen/RISCV/srem-lkk.ll
+++ b/llvm/test/CodeGen/RISCV/srem-lkk.ll
@@ -213,18 +213,17 @@ define i32 @combine_srem_sdiv(i32 %x) nounwind {
 ; RV32I-NEXT:    addi sp, sp, -16
 ; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
-; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    mv s0, a0
 ; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    call __modsi3
-; RV32I-NEXT:    mv s1, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s0
 ; RV32I-NEXT:    call __divsi3
-; RV32I-NEXT:    add a0, s1, a0
+; RV32I-NEXT:    slli a1, a0, 5
+; RV32I-NEXT:    slli a2, a0, 7
+; RV32I-NEXT:    add a1, a0, a1
+; RV32I-NEXT:    sub s0, s0, a2
+; RV32I-NEXT:    add a1, s0, a1
+; RV32I-NEXT:    add a0, a1, a0
 ; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
-; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    addi sp, sp, 16
 ; RV32I-NEXT:    ret
 ;
@@ -244,23 +243,22 @@ define i32 @combine_srem_sdiv(i32 %x) nounwind {
 ;
 ; RV64I-LABEL: combine_srem_sdiv:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    addi sp, sp, -32
-; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sext.w s0, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s0
-; RV64I-NEXT:    call __moddi3
-; RV64I-NEXT:    mv s1, a0
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s0, 0(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    mv s0, a0
+; RV64I-NEXT:    sext.w a0, a0
 ; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s0
 ; RV64I-NEXT:    call __divdi3
-; RV64I-NEXT:    addw a0, s1, a0
-; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    addi sp, sp, 32
+; RV64I-NEXT:    slli a1, a0, 5
+; RV64I-NEXT:    slli a2, a0, 7
+; RV64I-NEXT:    add a1, a0, a1
+; RV64I-NEXT:    sub s0, s0, a2
+; RV64I-NEXT:    add a1, s0, a1
+; RV64I-NEXT:    addw a0, a1, a0
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s0, 0(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
 ; RV64I-NEXT:    ret
 ;
 ; RV64IM-LABEL: combine_srem_sdiv:
diff --git a/llvm/test/CodeGen/RISCV/srem-vector-lkk.ll b/llvm/test/CodeGen/RISCV/srem-vector-lkk.ll
index 0cf8df1288e4b..907e31090d85d 100644
--- a/llvm/test/CodeGen/RISCV/srem-vector-lkk.ll
+++ b/llvm/test/CodeGen/RISCV/srem-vector-lkk.ll
@@ -375,7 +375,6 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT:    sw s8, 8(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    lh s1, 0(a1)
 ; RV32I-NEXT:    lh s2, 4(a1)
 ; RV32I-NEXT:    lh s3, 8(a1)
@@ -383,43 +382,47 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    mv s0, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s4
-; RV32I-NEXT:    call __modsi3
+; RV32I-NEXT:    call __divsi3
 ; RV32I-NEXT:    mv s5, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s5, 7
+; RV32I-NEXT:    add a0, s5, a0
+; RV32I-NEXT:    sub a1, s4, a1
+; RV32I-NEXT:    add s6, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s3
-; RV32I-NEXT:    call __modsi3
-; RV32I-NEXT:    mv s6, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s2
-; RV32I-NEXT:    call __modsi3
-; RV32I-NEXT:    mv s7, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s1
-; RV32I-NEXT:    call __modsi3
-; RV32I-NEXT:    mv s8, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s4
 ; RV32I-NEXT:    call __divsi3
 ; RV32I-NEXT:    mv s4, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s3
-; RV32I-NEXT:    call __divsi3
-; RV32I-NEXT:    mv s3, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s4, 7
+; RV32I-NEXT:    add a0, s4, a0
+; RV32I-NEXT:    sub a1, s3, a1
+; RV32I-NEXT:    add s7, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s2
 ; RV32I-NEXT:    call __divsi3
-; RV32I-NEXT:    mv s2, a0
+; RV32I-NEXT:    mv s3, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s3, 7
+; RV32I-NEXT:    add a0, s3, a0
+; RV32I-NEXT:    sub a1, s2, a1
+; RV32I-NEXT:    add s2, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s1
 ; RV32I-NEXT:    call __divsi3
-; RV32I-NEXT:    add s2, s7, s2
-; RV32I-NEXT:    add s3, s6, s3
-; RV32I-NEXT:    add a0, s8, a0
-; RV32I-NEXT:    add s4, s5, s4
+; RV32I-NEXT:    add s2, s2, s3
+; RV32I-NEXT:    slli a1, a0, 5
+; RV32I-NEXT:    slli a2, a0, 7
+; RV32I-NEXT:    add a1, a0, a1
+; RV32I-NEXT:    sub s1, s1, a2
+; RV32I-NEXT:    add s4, s7, s4
+; RV32I-NEXT:    add a1, s1, a1
+; RV32I-NEXT:    add s5, s6, s5
+; RV32I-NEXT:    add a0, a1, a0
 ; RV32I-NEXT:    sh a0, 0(s0)
 ; RV32I-NEXT:    sh s2, 2(s0)
-; RV32I-NEXT:    sh s3, 4(s0)
-; RV32I-NEXT:    sh s4, 6(s0)
+; RV32I-NEXT:    sh s4, 4(s0)
+; RV32I-NEXT:    sh s5, 6(s0)
 ; RV32I-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
@@ -429,7 +432,6 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
-; RV32I-NEXT:    lw s8, 8(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    addi sp, sp, 48
 ; RV32I-NEXT:    ret
 ;
@@ -488,7 +490,6 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    sd s5, 24(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    sd s6, 16(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    sd s7, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s8, 0(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    lh s1, 0(a1)
 ; RV64I-NEXT:    lh s2, 8(a1)
 ; RV64I-NEXT:    lh s3, 16(a1)
@@ -496,43 +497,47 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    mv s0, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s4
-; RV64I-NEXT:    call __moddi3
+; RV64I-NEXT:    call __divdi3
 ; RV64I-NEXT:    mv s5, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s5, 7
+; RV64I-NEXT:    add a0, s5, a0
+; RV64I-NEXT:    sub a1, s4, a1
+; RV64I-NEXT:    add s6, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s3
-; RV64I-NEXT:    call __moddi3
-; RV64I-NEXT:    mv s6, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s2
-; RV64I-NEXT:    call __moddi3
-; RV64I-NEXT:    mv s7, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s1
-; RV64I-NEXT:    call __moddi3
-; RV64I-NEXT:    mv s8, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s4
 ; RV64I-NEXT:    call __divdi3
 ; RV64I-NEXT:    mv s4, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s3
-; RV64I-NEXT:    call __divdi3
-; RV64I-NEXT:    mv s3, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s4, 7
+; RV64I-NEXT:    add a0, s4, a0
+; RV64I-NEXT:    sub a1, s3, a1
+; RV64I-NEXT:    add s7, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s2
 ; RV64I-NEXT:    call __divdi3
-; RV64I-NEXT:    mv s2, a0
+; RV64I-NEXT:    mv s3, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s3, 7
+; RV64I-NEXT:    add a0, s3, a0
+; RV64I-NEXT:    sub a1, s2, a1
+; RV64I-NEXT:    add s2, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s1
 ; RV64I-NEXT:    call __divdi3
-; RV64I-NEXT:    add s2, s7, s2
-; RV64I-NEXT:    add s3, s6, s3
-; RV64I-NEXT:    add a0, s8, a0
-; RV64I-NEXT:    add s4, s5, s4
+; RV64I-NEXT:    add s2, s2, s3
+; RV64I-NEXT:    slli a1, a0, 5
+; RV64I-NEXT:    slli a2, a0, 7
+; RV64I-NEXT:    add a1, a0, a1
+; RV64I-NEXT:    sub s1, s1, a2
+; RV64I-NEXT:    add s4, s7, s4
+; RV64I-NEXT:    add a1, s1, a1
+; RV64I-NEXT:    add s5, s6, s5
+; RV64I-NEXT:    add a0, a1, a0
 ; RV64I-NEXT:    sh a0, 0(s0)
 ; RV64I-NEXT:    sh s2, 2(s0)
-; RV64I-NEXT:    sh s3, 4(s0)
-; RV64I-NEXT:    sh s4, 6(s0)
+; RV64I-NEXT:    sh s4, 4(s0)
+; RV64I-NEXT:    sh s5, 6(s0)
 ; RV64I-NEXT:    ld ra, 72(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s0, 64(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s1, 56(sp) # 8-byte Folded Reload
@@ -542,7 +547,6 @@ define <4 x i16> @combine_srem_sdiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    ld s5, 24(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s6, 16(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s7, 8(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s8, 0(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    addi sp, sp, 80
 ; RV64I-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/RISCV/urem-lkk.ll b/llvm/test/CodeGen/RISCV/urem-lkk.ll
index 3d533db169c0d..32a267568b6de 100644
--- a/llvm/test/CodeGen/RISCV/urem-lkk.ll
+++ b/llvm/test/CodeGen/RISCV/urem-lkk.ll
@@ -109,18 +109,17 @@ define i32 @combine_urem_udiv(i32 %x) nounwind {
 ; RV32I-NEXT:    addi sp, sp, -16
 ; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s0, 8(sp) # 4-byte Folded Spill
-; RV32I-NEXT:    sw s1, 4(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    mv s0, a0
 ; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    call __umodsi3
-; RV32I-NEXT:    mv s1, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s0
 ; RV32I-NEXT:    call __udivsi3
-; RV32I-NEXT:    add a0, s1, a0
+; RV32I-NEXT:    slli a1, a0, 5
+; RV32I-NEXT:    slli a2, a0, 7
+; RV32I-NEXT:    add a1, a0, a1
+; RV32I-NEXT:    sub s0, s0, a2
+; RV32I-NEXT:    add a1, s0, a1
+; RV32I-NEXT:    add a0, a1, a0
 ; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s0, 8(sp) # 4-byte Folded Reload
-; RV32I-NEXT:    lw s1, 4(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    addi sp, sp, 16
 ; RV32I-NEXT:    ret
 ;
@@ -141,24 +140,23 @@ define i32 @combine_urem_udiv(i32 %x) nounwind {
 ;
 ; RV64I-LABEL: combine_urem_udiv:
 ; RV64I:       # %bb.0:
-; RV64I-NEXT:    addi sp, sp, -32
-; RV64I-NEXT:    sd ra, 24(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s0, 16(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s1, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    sd s0, 0(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    slli a0, a0, 32
 ; RV64I-NEXT:    srli s0, a0, 32
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s0
-; RV64I-NEXT:    call __umoddi3
-; RV64I-NEXT:    mv s1, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s0
 ; RV64I-NEXT:    call __udivdi3
-; RV64I-NEXT:    add a0, s1, a0
-; RV64I-NEXT:    ld ra, 24(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s0, 16(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s1, 8(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    addi sp, sp, 32
+; RV64I-NEXT:    slli a1, a0, 5
+; RV64I-NEXT:    slli a2, a0, 7
+; RV64I-NEXT:    add a1, a0, a1
+; RV64I-NEXT:    sub s0, s0, a2
+; RV64I-NEXT:    add a1, s0, a1
+; RV64I-NEXT:    add a0, a1, a0
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    ld s0, 0(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
 ; RV64I-NEXT:    ret
 ;
 ; RV64IM-LABEL: combine_urem_udiv:
diff --git a/llvm/test/CodeGen/RISCV/urem-vector-lkk.ll b/llvm/test/CodeGen/RISCV/urem-vector-lkk.ll
index f8325770a766b..b1a095c0f3aea 100644
--- a/llvm/test/CodeGen/RISCV/urem-vector-lkk.ll
+++ b/llvm/test/CodeGen/RISCV/urem-vector-lkk.ll
@@ -328,7 +328,6 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    sw s5, 20(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s6, 16(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    sw s7, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT:    sw s8, 8(sp) # 4-byte Folded Spill
 ; RV32I-NEXT:    lhu s1, 0(a1)
 ; RV32I-NEXT:    lhu s2, 4(a1)
 ; RV32I-NEXT:    lhu s3, 8(a1)
@@ -336,43 +335,47 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    mv s0, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s4
-; RV32I-NEXT:    call __umodsi3
+; RV32I-NEXT:    call __udivsi3
 ; RV32I-NEXT:    mv s5, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s5, 7
+; RV32I-NEXT:    add a0, s5, a0
+; RV32I-NEXT:    sub a1, s4, a1
+; RV32I-NEXT:    add s6, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s3
-; RV32I-NEXT:    call __umodsi3
-; RV32I-NEXT:    mv s6, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s2
-; RV32I-NEXT:    call __umodsi3
-; RV32I-NEXT:    mv s7, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s1
-; RV32I-NEXT:    call __umodsi3
-; RV32I-NEXT:    mv s8, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s4
 ; RV32I-NEXT:    call __udivsi3
 ; RV32I-NEXT:    mv s4, a0
-; RV32I-NEXT:    li a1, 95
-; RV32I-NEXT:    mv a0, s3
-; RV32I-NEXT:    call __udivsi3
-; RV32I-NEXT:    mv s3, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s4, 7
+; RV32I-NEXT:    add a0, s4, a0
+; RV32I-NEXT:    sub a1, s3, a1
+; RV32I-NEXT:    add s7, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s2
 ; RV32I-NEXT:    call __udivsi3
-; RV32I-NEXT:    mv s2, a0
+; RV32I-NEXT:    mv s3, a0
+; RV32I-NEXT:    slli a0, a0, 5
+; RV32I-NEXT:    slli a1, s3, 7
+; RV32I-NEXT:    add a0, s3, a0
+; RV32I-NEXT:    sub a1, s2, a1
+; RV32I-NEXT:    add s2, a1, a0
 ; RV32I-NEXT:    li a1, 95
 ; RV32I-NEXT:    mv a0, s1
 ; RV32I-NEXT:    call __udivsi3
-; RV32I-NEXT:    add s2, s7, s2
-; RV32I-NEXT:    add s3, s6, s3
-; RV32I-NEXT:    add a0, s8, a0
-; RV32I-NEXT:    add s4, s5, s4
+; RV32I-NEXT:    add s2, s2, s3
+; RV32I-NEXT:    slli a1, a0, 5
+; RV32I-NEXT:    slli a2, a0, 7
+; RV32I-NEXT:    add a1, a0, a1
+; RV32I-NEXT:    sub s1, s1, a2
+; RV32I-NEXT:    add s4, s7, s4
+; RV32I-NEXT:    add a1, s1, a1
+; RV32I-NEXT:    add s5, s6, s5
+; RV32I-NEXT:    add a0, a1, a0
 ; RV32I-NEXT:    sh a0, 0(s0)
 ; RV32I-NEXT:    sh s2, 2(s0)
-; RV32I-NEXT:    sh s3, 4(s0)
-; RV32I-NEXT:    sh s4, 6(s0)
+; RV32I-NEXT:    sh s4, 4(s0)
+; RV32I-NEXT:    sh s5, 6(s0)
 ; RV32I-NEXT:    lw ra, 44(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s0, 40(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s1, 36(sp) # 4-byte Folded Reload
@@ -382,7 +385,6 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV32I-NEXT:    lw s5, 20(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s6, 16(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    lw s7, 12(sp) # 4-byte Folded Reload
-; RV32I-NEXT:    lw s8, 8(sp) # 4-byte Folded Reload
 ; RV32I-NEXT:    addi sp, sp, 48
 ; RV32I-NEXT:    ret
 ;
@@ -429,7 +431,6 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    sd s5, 24(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    sd s6, 16(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    sd s7, 8(sp) # 8-byte Folded Spill
-; RV64I-NEXT:    sd s8, 0(sp) # 8-byte Folded Spill
 ; RV64I-NEXT:    lhu s1, 0(a1)
 ; RV64I-NEXT:    lhu s2, 8(a1)
 ; RV64I-NEXT:    lhu s3, 16(a1)
@@ -437,43 +438,47 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    mv s0, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s4
-; RV64I-NEXT:    call __umoddi3
+; RV64I-NEXT:    call __udivdi3
 ; RV64I-NEXT:    mv s5, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s5, 7
+; RV64I-NEXT:    add a0, s5, a0
+; RV64I-NEXT:    sub a1, s4, a1
+; RV64I-NEXT:    add s6, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s3
-; RV64I-NEXT:    call __umoddi3
-; RV64I-NEXT:    mv s6, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s2
-; RV64I-NEXT:    call __umoddi3
-; RV64I-NEXT:    mv s7, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s1
-; RV64I-NEXT:    call __umoddi3
-; RV64I-NEXT:    mv s8, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s4
 ; RV64I-NEXT:    call __udivdi3
 ; RV64I-NEXT:    mv s4, a0
-; RV64I-NEXT:    li a1, 95
-; RV64I-NEXT:    mv a0, s3
-; RV64I-NEXT:    call __udivdi3
-; RV64I-NEXT:    mv s3, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s4, 7
+; RV64I-NEXT:    add a0, s4, a0
+; RV64I-NEXT:    sub a1, s3, a1
+; RV64I-NEXT:    add s7, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s2
 ; RV64I-NEXT:    call __udivdi3
-; RV64I-NEXT:    mv s2, a0
+; RV64I-NEXT:    mv s3, a0
+; RV64I-NEXT:    slli a0, a0, 5
+; RV64I-NEXT:    slli a1, s3, 7
+; RV64I-NEXT:    add a0, s3, a0
+; RV64I-NEXT:    sub a1, s2, a1
+; RV64I-NEXT:    add s2, a1, a0
 ; RV64I-NEXT:    li a1, 95
 ; RV64I-NEXT:    mv a0, s1
 ; RV64I-NEXT:    call __udivdi3
-; RV64I-NEXT:    add s2, s7, s2
-; RV64I-NEXT:    add s3, s6, s3
-; RV64I-NEXT:    add a0, s8, a0
-; RV64I-NEXT:    add s4, s5, s4
+; RV64I-NEXT:    add s2, s2, s3
+; RV64I-NEXT:    slli a1, a0, 5
+; RV64I-NEXT:    slli a2, a0, 7
+; RV64I-NEXT:    add a1, a0, a1
+; RV64I-NEXT:    sub s1, s1, a2
+; RV64I-NEXT:    add s4, s7, s4
+; RV64I-NEXT:    add a1, s1, a1
+; RV64I-NEXT:    add s5, s6, s5
+; RV64I-NEXT:    add a0, a1, a0
 ; RV64I-NEXT:    sh a0, 0(s0)
 ; RV64I-NEXT:    sh s2, 2(s0)
-; RV64I-NEXT:    sh s3, 4(s0)
-; RV64I-NEXT:    sh s4, 6(s0)
+; RV64I-NEXT:    sh s4, 4(s0)
+; RV64I-NEXT:    sh s5, 6(s0)
 ; RV64I-NEXT:    ld ra, 72(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s0, 64(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s1, 56(sp) # 8-byte Folded Reload
@@ -483,7 +488,6 @@ define <4 x i16> @combine_urem_udiv(<4 x i16> %x) nounwind {
 ; RV64I-NEXT:    ld s5, 24(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s6, 16(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    ld s7, 8(sp) # 8-byte Folded Reload
-; RV64I-NEXT:    ld s8, 0(sp) # 8-byte Folded Reload
 ; RV64I-NEXT:    addi sp, sp, 80
 ; RV64I-NEXT:    ret
 ;



More information about the llvm-commits mailing list