diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad
index 0c19b7b44c7..367e3807be4 100644
--- a/src/hotspot/cpu/aarch64/aarch64.ad
+++ b/src/hotspot/cpu/aarch64/aarch64.ad
@@ -2796,6 +2796,10 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack,
   return false;
 }
 
+bool Parse::do_one_bytecode_targeted() {
+  return false;
+}
+
 #define MOV_VOLATILE(REG, BASE, INDEX, SCALE, DISP, SCRATCH, INSN)      \
   C2_MacroAssembler _masm(&cbuf);                                       \
   {                                                                     \
diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad
index a801ff1217c..30453202d00 100644
--- a/src/hotspot/cpu/arm/arm.ad
+++ b/src/hotspot/cpu/arm/arm.ad
@@ -1159,6 +1159,10 @@ bool maybe_far_call(const MachCallNode *n) {
   return !MacroAssembler::_reachable_from_cache(n->as_MachCall()->entry_point());
 }
 
+bool Parse::do_one_bytecode_targeted() {
+  return false;
+}
+
 %}
 
 //----------ENCODING BLOCK-----------------------------------------------------
diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad
index d94daeb0f36..d9e925ad82e 100644
--- a/src/hotspot/cpu/ppc/ppc.ad
+++ b/src/hotspot/cpu/ppc/ppc.ad
@@ -2407,6 +2407,10 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
   return RegMask();
 }
 
+bool Parse::do_one_bytecode_targeted() {
+  return false;
+}
+
 %}
 
 //----------ENCODING BLOCK-----------------------------------------------------
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index 518e6853126..c13bef4288b 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -2044,6 +2044,10 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack,
   return clone_base_plus_offset_address(m, mstack, address_visited);
 }
 
+bool Parse::do_one_bytecode_targeted() {
+  return false;
+}
+
 %}
 
 
diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad
index b3ad4afe979..72a9f11cbca 100644
--- a/src/hotspot/cpu/s390/s390.ad
+++ b/src/hotspot/cpu/s390/s390.ad
@@ -1698,6 +1698,10 @@ bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack,
   return clone_base_plus_offset_address(m, mstack, address_visited);
 }
 
+bool Parse::do_one_bytecode_targeted() {
+  return false;
+}
+
 %} // source
 
 //----------ENCODING BLOCK-----------------------------------------------------
diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp
index 8502953e870..6eab69a900a 100644
--- a/src/hotspot/cpu/x86/assembler_x86.cpp
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp
@@ -2235,6 +2235,13 @@ void Assembler::idivl(Register src) {
   emit_int16((unsigned char)0xF7, (0xF8 | encode));
 }
 
+void Assembler::idivl(Address src) {
+  InstructionMark im(this);
+  prefix(src);
+  emit_int8((unsigned char)0xF7);
+  emit_operand(as_Register(7), src);
+}
+
 void Assembler::divl(Register src) { // Unsigned
   int encode = prefix_and_encode(src->encoding());
   emit_int16((unsigned char)0xF7, (0xF0 | encode));
@@ -12366,6 +12373,13 @@ void Assembler::idivq(Register src) {
   emit_int16((unsigned char)0xF7, (0xF8 | encode));
 }
 
+void Assembler::idivq(Address src) {
+  InstructionMark im(this);
+  prefixq(src);
+  emit_int8((unsigned char)0xF7);
+  emit_operand(as_Register(7), src);
+}
+
 void Assembler::divq(Register src) {
   int encode = prefixq_and_encode(src->encoding());
   emit_int16((unsigned char)0xF7, (0xF0 | encode));
diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp
index 3f03f91aeec..241bd3e96e6 100644
--- a/src/hotspot/cpu/x86/assembler_x86.hpp
+++ b/src/hotspot/cpu/x86/assembler_x86.hpp
@@ -1196,6 +1196,9 @@ private:
   void vpabsd(XMMRegister dst, XMMRegister src, int vector_len);
   void evpabsq(XMMRegister dst, XMMRegister src, int vector_len);
 
+  void divl(Register src);
+  void divq(Register src);
+
   // Divide Scalar Double-Precision Floating-Point Values
   void divsd(XMMRegister dst, Address src);
   void divsd(XMMRegister dst, XMMRegister src);
@@ -1364,12 +1367,9 @@ private:
   void hlt();
 
   void idivl(Register src);
-  void divl(Register src); // Unsigned division
-
-#ifdef _LP64
+  void idivl(Address src);
   void idivq(Register src);
-  void divq(Register src); // Unsigned division
-#endif
+  void idivq(Address src);
 
   void imull(Register src);
   void imull(Register dst, Register src);
diff --git a/src/hotspot/cpu/x86/parse_x86.cpp b/src/hotspot/cpu/x86/parse_x86.cpp
new file mode 100644
index 00000000000..be283a3d9f1
--- /dev/null
+++ b/src/hotspot/cpu/x86/parse_x86.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+
+#ifdef COMPILER2
+
+#include "opto/parse.hpp"
+#include "interpreter/bytecodes.hpp"
+
+bool Parse::do_one_bytecode_targeted() {
+  switch (bc()) {
+    case Bytecodes::_idiv: // fallthrough
+    case Bytecodes::_irem: // fallthrough
+#ifdef _LP64
+    case Bytecodes::_ldiv: // fallthrough
+    case Bytecodes::_lrem:
+#endif
+      do_divmod_fixup();
+      return true;
+    default:
+      return false;
+  }
+}
+
+#endif // COMPILER2
diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad
index 385a8ebb27e..00283e21743 100644
--- a/src/hotspot/cpu/x86/x86_32.ad
+++ b/src/hotspot/cpu/x86/x86_32.ad
@@ -1556,47 +1556,6 @@ encode %{
     emit_d32   ( cbuf, 0x0  );             //                         imm32==0x0
   %}
 
-  enc_class cdq_enc %{
-    // Full implementation of Java idiv and irem; checks for
-    // special case as described in JVM spec., p.243 & p.271.
-    //
-    //         normal case                           special case
-    //
-    // input : rax,: dividend                         min_int
-    //         reg: divisor                          -1
-    //
-    // output: rax,: quotient  (= rax, idiv reg)       min_int
-    //         rdx: remainder (= rax, irem reg)       0
-    //
-    //  Code sequnce:
-    //
-    //  81 F8 00 00 00 80    cmp         rax,80000000h
-    //  0F 85 0B 00 00 00    jne         normal_case
-    //  33 D2                xor         rdx,edx
-    //  83 F9 FF             cmp         rcx,0FFh
-    //  0F 84 03 00 00 00    je          done
-    //                  normal_case:
-    //  99                   cdq
-    //  F7 F9                idiv        rax,ecx
-    //                  done:
-    //
-    emit_opcode(cbuf,0x81); emit_d8(cbuf,0xF8);
-    emit_opcode(cbuf,0x00); emit_d8(cbuf,0x00);
-    emit_opcode(cbuf,0x00); emit_d8(cbuf,0x80);                     // cmp rax,80000000h
-    emit_opcode(cbuf,0x0F); emit_d8(cbuf,0x85);
-    emit_opcode(cbuf,0x0B); emit_d8(cbuf,0x00);
-    emit_opcode(cbuf,0x00); emit_d8(cbuf,0x00);                     // jne normal_case
-    emit_opcode(cbuf,0x33); emit_d8(cbuf,0xD2);                     // xor rdx,edx
-    emit_opcode(cbuf,0x83); emit_d8(cbuf,0xF9); emit_d8(cbuf,0xFF); // cmp rcx,0FFh
-    emit_opcode(cbuf,0x0F); emit_d8(cbuf,0x84);
-    emit_opcode(cbuf,0x03); emit_d8(cbuf,0x00);
-    emit_opcode(cbuf,0x00); emit_d8(cbuf,0x00);                     // je done
-    // normal_case:
-    emit_opcode(cbuf,0x99);                                         // cdq
-    // idiv (note: must be emitted by the user of this rule)
-    // normal:
-  %}
-
   // Dense encoding for older common ops
   enc_class Opc_plus(immI opcode, rRegI reg) %{
     emit_opcode(cbuf, $opcode$$constant + $reg$$reg);
@@ -7797,21 +7756,17 @@ instruct mulL_eReg_con(eADXRegL dst, immL_127 src, rRegI tmp, eFlagsReg cr) %{
 
 // Integer DIV with Register
 instruct divI_eReg(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
-  match(Set rax (DivI rax div));
+  match(Set rax (NoOvfDivI rax div));
   effect(KILL rdx, KILL cr);
-  size(26);
-  ins_cost(30*100+10*100);
-  format %{ "CMP    EAX,0x80000000\n\t"
-            "JNE,s  normal\n\t"
-            "XOR    EDX,EDX\n\t"
-            "CMP    ECX,-1\n\t"
-            "JE,s   done\n"
-    "normal: CDQ\n\t"
-            "IDIV   $div\n\t"
-    "done:"        %}
-  opcode(0xF7, 0x7);  /* Opcode F7 /7 */
-  ins_encode( cdq_enc, OpcP, RegOpc(div) );
-  ins_pipe( ialu_reg_reg_alu0 );
+  size(3);
+  ins_cost(500);
+  format %{ "CDQ\n\t"
+            "IDIV   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
+  ins_pipe( pipe_slow );
 %}
 
 // Divide Register Long
@@ -7831,35 +7786,33 @@ instruct divL_eReg(eADXRegL dst, eRegL src1, eRegL src2) %{
 
 // Integer DIVMOD with Register, both quotient and mod results
 instruct divModI_eReg_divmod(eAXRegI rax, eDXRegI rdx, eCXRegI div, eFlagsReg cr) %{
-  match(DivModI rax div);
+  match(NoOvfDivModI rax div);
   effect(KILL cr);
-  size(26);
-  ins_cost(30*100+10*100);
-  format %{ "CMP    EAX,0x80000000\n\t"
-            "JNE,s  normal\n\t"
-            "XOR    EDX,EDX\n\t"
-            "CMP    ECX,-1\n\t"
-            "JE,s   done\n"
-    "normal: CDQ\n\t"
-            "IDIV   $div\n\t"
-    "done:"        %}
-  opcode(0xF7, 0x7);  /* Opcode F7 /7 */
-  ins_encode( cdq_enc, OpcP, RegOpc(div) );
+  size(3);
+  ins_cost(500);
+  format %{ "CDQ\n\t"
+            "IDIV   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
   ins_pipe( pipe_slow );
 %}
 
 // Integer MOD with Register
 instruct modI_eReg(eDXRegI rdx, eAXRegI rax, eCXRegI div, eFlagsReg cr) %{
-  match(Set rdx (ModI rax div));
+  match(Set rdx (NoOvfModI rax div));
   effect(KILL rax, KILL cr);
 
-  size(26);
-  ins_cost(300);
+  size(3);
+  ins_cost(500);
   format %{ "CDQ\n\t"
             "IDIV   $div" %}
-  opcode(0xF7, 0x7);  /* Opcode F7 /7 */
-  ins_encode( cdq_enc, OpcP, RegOpc(div) );
-  ins_pipe( ialu_reg_reg_alu0 );
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
+  ins_pipe( pipe_slow );
 %}
 
 // Remainder Register Long
diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad
index 369ef5f632a..c81605a73d7 100644
--- a/src/hotspot/cpu/x86/x86_64.ad
+++ b/src/hotspot/cpu/x86/x86_64.ad
@@ -338,11 +338,19 @@ extern RegMask _FLOAT_REG_mask;
 
 extern RegMask _STACK_OR_PTR_REG_mask;
 extern RegMask _STACK_OR_LONG_REG_mask;
+extern RegMask _STACK_OR_LONG_NO_RAX_RDX_REG_mask;
 extern RegMask _STACK_OR_INT_REG_mask;
+extern RegMask _STACK_OR_INT_NO_RAX_RDX_REG_mask;
 
 inline const RegMask& STACK_OR_PTR_REG_mask()  { return _STACK_OR_PTR_REG_mask;  }
 inline const RegMask& STACK_OR_LONG_REG_mask() { return _STACK_OR_LONG_REG_mask; }
+inline const RegMask& STACK_OR_LONG_NO_RAX_RDX_REG_mask() {
+  return _STACK_OR_LONG_NO_RAX_RDX_REG_mask;
+}
 inline const RegMask& STACK_OR_INT_REG_mask()  { return _STACK_OR_INT_REG_mask;  }
+inline const RegMask& STACK_OR_INT_NO_RAX_RDX_REG_mask() {
+  return _STACK_OR_INT_NO_RAX_RDX_REG_mask;
+}
 
 %}
 
@@ -368,7 +376,9 @@ RegMask _INT_NO_RBP_R13_REG_mask;
 RegMask _FLOAT_REG_mask;
 RegMask _STACK_OR_PTR_REG_mask;
 RegMask _STACK_OR_LONG_REG_mask;
+RegMask _STACK_OR_LONG_NO_RAX_RDX_REG_mask;
 RegMask _STACK_OR_INT_REG_mask;
+RegMask _STACK_OR_INT_NO_RAX_RDX_REG_mask;
 
 static bool need_r12_heapbase() {
   return UseCompressedOops;
@@ -429,6 +439,9 @@ void reg_mask_init() {
   _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()));
   _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()->next()));
 
+  _STACK_OR_LONG_NO_RAX_RDX_REG_mask = _LONG_NO_RAX_RDX_REG_mask;
+  _STACK_OR_LONG_NO_RAX_RDX_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
+
   _INT_REG_mask = _ALL_INT_REG_mask;
   if (PreserveFramePointer) {
     _INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
@@ -451,6 +464,9 @@ void reg_mask_init() {
   _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()));
   _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()));
 
+  _STACK_OR_INT_NO_RAX_RDX_REG_mask = _INT_NO_RAX_RDX_REG_mask;
+  _STACK_OR_INT_NO_RAX_RDX_REG_mask.OR(STACK_OR_STACK_SLOTS_mask());
+
   // _FLOAT_REG_LEGACY_mask/_FLOAT_REG_EVEX_mask is generated by adlc
   // from the float_reg_legacy/float_reg_evex register class.
   _FLOAT_REG_mask = VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask;
@@ -1907,123 +1923,6 @@ encode %{
     emit_rm(cbuf, 0x3, $dst$$reg & 7, $src$$reg & 7);
   %}
 
-  enc_class cdql_enc(no_rax_rdx_RegI div)
-  %{
-    // Full implementation of Java idiv and irem; checks for
-    // special case as described in JVM spec., p.243 & p.271.
-    //
-    //         normal case                           special case
-    //
-    // input : rax: dividend                         min_int
-    //         reg: divisor                          -1
-    //
-    // output: rax: quotient  (= rax idiv reg)       min_int
-    //         rdx: remainder (= rax irem reg)       0
-    //
-    //  Code sequnce:
-    //
-    //    0:   3d 00 00 00 80          cmp    $0x80000000,%eax
-    //    5:   75 07/08                jne    e <normal>
-    //    7:   33 d2                   xor    %edx,%edx
-    //  [div >= 8 -> offset + 1]
-    //  [REX_B]
-    //    9:   83 f9 ff                cmp    $0xffffffffffffffff,$div
-    //    c:   74 03/04                je     11 <done>
-    // 000000000000000e <normal>:
-    //    e:   99                      cltd
-    //  [div >= 8 -> offset + 1]
-    //  [REX_B]
-    //    f:   f7 f9                   idiv   $div
-    // 0000000000000011 <done>:
-    MacroAssembler _masm(&cbuf);
-    Label normal;
-    Label done;
-
-    // cmp    $0x80000000,%eax
-    __ cmpl(as_Register(RAX_enc), 0x80000000);
-
-    // jne    e <normal>
-    __ jccb(Assembler::notEqual, normal);
-
-    // xor    %edx,%edx
-    __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
-
-    // cmp    $0xffffffffffffffff,%ecx
-    __ cmpl($div$$Register, -1);
-
-    // je     11 <done>
-    __ jccb(Assembler::equal, done);
-
-    // <normal>
-    // cltd
-    __ bind(normal);
-    __ cdql();
-
-    // idivl
-    // <done>
-    __ idivl($div$$Register);
-    __ bind(done);
-  %}
-
-  enc_class cdqq_enc(no_rax_rdx_RegL div)
-  %{
-    // Full implementation of Java ldiv and lrem; checks for
-    // special case as described in JVM spec., p.243 & p.271.
-    //
-    //         normal case                           special case
-    //
-    // input : rax: dividend                         min_long
-    //         reg: divisor                          -1
-    //
-    // output: rax: quotient  (= rax idiv reg)       min_long
-    //         rdx: remainder (= rax irem reg)       0
-    //
-    //  Code sequnce:
-    //
-    //    0:   48 ba 00 00 00 00 00    mov    $0x8000000000000000,%rdx
-    //    7:   00 00 80
-    //    a:   48 39 d0                cmp    %rdx,%rax
-    //    d:   75 08                   jne    17 <normal>
-    //    f:   33 d2                   xor    %edx,%edx
-    //   11:   48 83 f9 ff             cmp    $0xffffffffffffffff,$div
-    //   15:   74 05                   je     1c <done>
-    // 0000000000000017 <normal>:
-    //   17:   48 99                   cqto
-    //   19:   48 f7 f9                idiv   $div
-    // 000000000000001c <done>:
-    MacroAssembler _masm(&cbuf);
-    Label normal;
-    Label done;
-
-    // mov    $0x8000000000000000,%rdx
-    __ mov64(as_Register(RDX_enc), 0x8000000000000000);
-
-    // cmp    %rdx,%rax
-    __ cmpq(as_Register(RAX_enc), as_Register(RDX_enc));
-
-    // jne    17 <normal>
-    __ jccb(Assembler::notEqual, normal);
-
-    // xor    %edx,%edx
-    __ xorl(as_Register(RDX_enc), as_Register(RDX_enc));
-
-    // cmp    $0xffffffffffffffff,$div
-    __ cmpq($div$$Register, -1);
-
-    // je     1e <done>
-    __ jccb(Assembler::equal, done);
-
-    // <normal>
-    // cqto
-    __ bind(normal);
-    __ cdqq();
-
-    // idivq (note: must be emitted by the user of this rule)
-    // <done>
-    __ idivq($div$$Register);
-    __ bind(done);
-  %}
-
   // Opcde enc_class for 8/32 bit immediate instructions with sign-extension
   enc_class OpcSE(immI imm)
   %{
@@ -8652,40 +8551,65 @@ instruct umulHiL_rReg(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr)
 instruct divI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
                    rFlagsReg cr)
 %{
-  match(Set rax (DivI rax div));
+  match(Set rax (NoOvfDivI rax div));
   effect(KILL rdx, KILL cr);
 
-  ins_cost(30*100+10*100); // XXX
-  format %{ "cmpl    rax, 0x80000000\t# idiv\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpl    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdql\n\t"
-            "idivl   $div\n"
-    "done:"        %}
-  ins_encode(cdql_enc(div));
-  ins_pipe(ialu_reg_reg_alu0);
+  ins_cost(500);
+  format %{ "cdql\n\t"
+            "idivl   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct divI_mem(rax_RegI rax, rdx_RegI rdx, memory div,
+                   rFlagsReg cr)
+%{
+  match(Set rax (NoOvfDivI rax (LoadI div)));
+  effect(KILL rdx, KILL cr);
+
+  ins_cost(575);
+  format %{ "cdql\n\t"
+            "idivl   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Address);
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct divL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
                    rFlagsReg cr)
 %{
-  match(Set rax (DivL rax div));
+  match(Set rax (NoOvfDivL rax div));
   effect(KILL rdx, KILL cr);
 
-  ins_cost(30*100+10*100); // XXX
-  format %{ "movq    rdx, 0x8000000000000000\t# ldiv\n\t"
-            "cmpq    rax, rdx\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpq    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdqq\n\t"
-            "idivq   $div\n"
-    "done:"        %}
-  ins_encode(cdqq_enc(div));
-  ins_pipe(ialu_reg_reg_alu0);
+  ins_cost(500);
+  format %{ "cdqq\n\t"
+            "idivq   $div" %}
+  ins_encode %{
+    __ cdqq();
+    __ idivq($div$$Register);
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct divL_mem(rax_RegL rax, rdx_RegL rdx, memory div,
+                   rFlagsReg cr)
+%{
+  match(Set rax (NoOvfDivL rax (LoadL div)));
+  effect(KILL rdx, KILL cr);
+
+  ins_cost(575);
+  format %{ "cdqq\n\t"
+            "idivq   $div" %}
+  ins_encode %{
+    __ cdqq();
+    __ idivq($div$$Address);
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct udivI_rReg(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div, rFlagsReg cr)
@@ -8718,19 +8642,16 @@ instruct udivL_rReg(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div, rFlagsReg c
 instruct divModI_rReg_divmod(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
                              rFlagsReg cr)
 %{
-  match(DivModI rax div);
+  match(NoOvfDivModI rax div);
   effect(KILL cr);
 
-  ins_cost(30*100+10*100); // XXX
-  format %{ "cmpl    rax, 0x80000000\t# idiv\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpl    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdql\n\t"
-            "idivl   $div\n"
-    "done:"        %}
-  ins_encode(cdql_enc(div));
+  ins_cost(500);
+  format %{ "cdql\n\t"
+            "idivl   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -8738,20 +8659,16 @@ instruct divModI_rReg_divmod(rax_RegI rax, rdx_RegI rdx, no_rax_rdx_RegI div,
 instruct divModL_rReg_divmod(rax_RegL rax, rdx_RegL rdx, no_rax_rdx_RegL div,
                              rFlagsReg cr)
 %{
-  match(DivModL rax div);
+  match(NoOvfDivModL rax div);
   effect(KILL cr);
 
-  ins_cost(30*100+10*100); // XXX
-  format %{ "movq    rdx, 0x8000000000000000\t# ldiv\n\t"
-            "cmpq    rax, rdx\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpq    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdqq\n\t"
-            "idivq   $div\n"
-    "done:"        %}
-  ins_encode(cdqq_enc(div));
+  ins_cost(500);
+  format %{ "cdqq\n\t"
+            "idivq   $div" %}
+  ins_encode %{
+    __ cdqq();
+    __ idivq($div$$Register);
+  %}
   ins_pipe(pipe_slow);
 %}
 
@@ -8789,108 +8706,68 @@ instruct udivModL_rReg_divmod(rax_RegL rax, no_rax_rdx_RegL tmp, rdx_RegL rdx,
   ins_pipe(pipe_slow);
 %}
 
-
-//----------- DivL-By-Constant-Expansions--------------------------------------
-// DivI cases are handled by the compiler
-
-// Magic constant, reciprocal of 10
-instruct loadConL_0x6666666666666667(rRegL dst)
-%{
-  effect(DEF dst);
-
-  format %{ "movq    $dst, #0x666666666666667\t# Used in div-by-10" %}
-  ins_encode(load_immL(dst, 0x6666666666666667));
-  ins_pipe(ialu_reg);
-%}
-
-instruct mul_hi(rdx_RegL dst, no_rax_RegL src, rax_RegL rax, rFlagsReg cr)
-%{
-  effect(DEF dst, USE src, USE_KILL rax, KILL cr);
-
-  format %{ "imulq   rdx:rax, rax, $src\t# Used in div-by-10" %}
-  ins_encode %{
-    __ imulq($src$$Register);
-  %}
-  ins_pipe(ialu_reg_reg_alu0);
-%}
-
-instruct sarL_rReg_63(rRegL dst, rFlagsReg cr)
-%{
-  effect(USE_DEF dst, KILL cr);
-
-  format %{ "sarq    $dst, #63\t# Used in div-by-10" %}
-  ins_encode %{
-    __ sarq($dst$$Register, 63);
-  %}
-  ins_pipe(ialu_reg);
-%}
-
-instruct sarL_rReg_2(rRegL dst, rFlagsReg cr)
-%{
-  effect(USE_DEF dst, KILL cr);
-
-  format %{ "sarq    $dst, #2\t# Used in div-by-10" %}
-  ins_encode %{
-    __ sarq($dst$$Register, 2);
-  %}
-  ins_pipe(ialu_reg);
-%}
-
-instruct divL_10(rdx_RegL dst, no_rax_RegL src, immL10 div)
-%{
-  match(Set dst (DivL src div));
-
-  ins_cost((5+8)*100);
-  expand %{
-    rax_RegL rax;                     // Killed temp
-    rFlagsReg cr;                     // Killed
-    loadConL_0x6666666666666667(rax); // movq  rax, 0x6666666666666667
-    mul_hi(dst, src, rax, cr);        // mulq  rdx:rax <= rax * $src
-    sarL_rReg_63(src, cr);            // sarq  src, 63
-    sarL_rReg_2(dst, cr);             // sarq  rdx, 2
-    subL_rReg(dst, src, cr);          // subl  rdx, src
-  %}
-%}
-
-//-----------------------------------------------------------------------------
-
 instruct modI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div,
                    rFlagsReg cr)
 %{
-  match(Set rdx (ModI rax div));
+  match(Set rdx (NoOvfModI rax div));
   effect(KILL rax, KILL cr);
 
-  ins_cost(300); // XXX
-  format %{ "cmpl    rax, 0x80000000\t# irem\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpl    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdql\n\t"
-            "idivl   $div\n"
-    "done:"        %}
-  ins_encode(cdql_enc(div));
-  ins_pipe(ialu_reg_reg_alu0);
+  ins_cost(500);
+  format %{ "cdql\n\t"
+            "idivl   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Register);
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct modI_mem(rdx_RegI rdx, rax_RegI rax, memory div,
+                   rFlagsReg cr)
+%{
+  match(Set rdx (NoOvfModI rax (LoadI div)));
+  effect(KILL rax, KILL cr);
+
+  ins_cost(575);
+  format %{ "cdql\n\t"
+            "idivl   $div" %}
+  ins_encode %{
+    __ cdql();
+    __ idivl($div$$Address);
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct modL_rReg(rdx_RegL rdx, rax_RegL rax, no_rax_rdx_RegL div,
                    rFlagsReg cr)
 %{
-  match(Set rdx (ModL rax div));
+  match(Set rdx (NoOvfModL rax div));
   effect(KILL rax, KILL cr);
 
-  ins_cost(300); // XXX
-  format %{ "movq    rdx, 0x8000000000000000\t# lrem\n\t"
-            "cmpq    rax, rdx\n\t"
-            "jne,s   normal\n\t"
-            "xorl    rdx, rdx\n\t"
-            "cmpq    $div, -1\n\t"
-            "je,s    done\n"
-    "normal: cdqq\n\t"
-            "idivq   $div\n"
-    "done:"        %}
-  ins_encode(cdqq_enc(div));
-  ins_pipe(ialu_reg_reg_alu0);
+  ins_cost(500);
+  format %{ "cdqq\n\t"
+            "idivq   $div" %}
+  ins_encode %{
+    __ cdqq();
+    __ idivq($div$$Register);
+  %}
+  ins_pipe(pipe_slow);
+%}
+
+instruct modL_mem(rdx_RegL rdx, rax_RegL rax, memory div,
+                   rFlagsReg cr)
+%{
+  match(Set rdx (NoOvfModL rax (LoadL div)));
+  effect(KILL rax, KILL cr);
+
+  ins_cost(575);
+  format %{ "cdqq\n\t"
+            "idivq   $div" %}
+  ins_encode %{
+    __ cdqq();
+    __ idivq($div$$Address);
+  %}
+  ins_pipe(pipe_slow);
 %}
 
 instruct umodI_rReg(rdx_RegI rdx, rax_RegI rax, no_rax_rdx_RegI div, rFlagsReg cr)
diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp
index 0336209f5f9..d536f6e25ac 100644
--- a/src/hotspot/share/adlc/main.cpp
+++ b/src/hotspot/share/adlc/main.cpp
@@ -226,6 +226,7 @@ int main(int argc, char *argv[])
   AD.addInclude(AD._CPP_file, "opto/intrinsicnode.hpp");
   AD.addInclude(AD._CPP_file, "opto/locknode.hpp");
   AD.addInclude(AD._CPP_file, "opto/opcodes.hpp");
+  AD.addInclude(AD._CPP_file, "opto/parse.hpp");
   AD.addInclude(AD._CPP_file, "opto/regalloc.hpp");
   AD.addInclude(AD._CPP_file, "opto/regmask.hpp");
   AD.addInclude(AD._CPP_file, "opto/runtime.hpp");
diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp
index 45bd30d6899..3fc2c143ad4 100644
--- a/src/hotspot/share/opto/classes.hpp
+++ b/src/hotspot/share/opto/classes.hpp
@@ -162,11 +162,15 @@ macro(DivD)
 macro(DivF)
 macro(DivI)
 macro(DivL)
+macro(NoOvfDivI)
+macro(NoOvfDivL)
 macro(UDivI)
 macro(UDivL)
 macro(DivMod)
 macro(DivModI)
 macro(DivModL)
+macro(NoOvfDivModI)
+macro(NoOvfDivModL)
 macro(UDivModI)
 macro(UDivModL)
 macro(EncodeISOArray)
@@ -235,6 +239,8 @@ macro(ModD)
 macro(ModF)
 macro(ModI)
 macro(ModL)
+macro(NoOvfModI)
+macro(NoOvfModL)
 macro(UModI)
 macro(UModL)
 macro(MoveI2F)
diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp
index 418a2cbda0f..edcc3bcca5b 100644
--- a/src/hotspot/share/opto/compile.cpp
+++ b/src/hotspot/share/opto/compile.cpp
@@ -3529,6 +3529,46 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f
     }
     break;
 
+  case Op_NoOvfModI:
+    if (UseDivMod) {
+      // Check if a%b and a/b both exist
+      Node* d = n->find_similar(Op_NoOvfDivI);
+      if (d) {
+        // Replace them with a fused divmod if supported
+        if (Matcher::has_match_rule(Op_NoOvfDivModI)) {
+          NoOvfDivModINode* divmod = NoOvfDivModINode::make(n);
+          d->subsume_by(divmod->div_proj(), this);
+          n->subsume_by(divmod->mod_proj(), this);
+        } else {
+          // replace a%b with a-((a/b)*b)
+          Node* mult = new MulINode(d, d->in(2));
+          Node* sub  = new SubINode(d->in(1), mult);
+          n->subsume_by(sub, this);
+        }
+      }
+    }
+    break;
+
+  case Op_NoOvfModL:
+    if (UseDivMod) {
+      // Check if a%b and a/b both exist
+      Node* d = n->find_similar(Op_NoOvfDivL);
+      if (d) {
+        // Replace them with a fused divmod if supported
+        if (Matcher::has_match_rule(Op_NoOvfDivModL)) {
+          NoOvfDivModLNode* divmod = NoOvfDivModLNode::make(n);
+          d->subsume_by(divmod->div_proj(), this);
+          n->subsume_by(divmod->mod_proj(), this);
+        } else {
+          // replace a%b with a-((a/b)*b)
+          Node* mult = new MulLNode(d, d->in(2));
+          Node* sub  = new SubLNode(d->in(1), mult);
+          n->subsume_by(sub, this);
+        }
+      }
+    }
+    break;
+
   case Op_LoadVector:
   case Op_StoreVector:
   case Op_LoadVectorGather:
diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp
index c76721e5466..0fd27e329f5 100644
--- a/src/hotspot/share/opto/divnode.cpp
+++ b/src/hotspot/share/opto/divnode.cpp
@@ -1466,3 +1466,27 @@ Node* UDivModLNode::match( const ProjNode *proj, const Matcher *match ) {
   }
   return new MachProjNode(this, proj->_con, rm, ideal_reg);
 }
+
+//------------------------------make------------------------------------------
+NoOvfDivModINode* NoOvfDivModINode::make(Node* div_or_mod) {
+  Node* n = div_or_mod;
+  assert(n->Opcode() == Op_NoOvfDivI || n->Opcode() == Op_NoOvfModI,
+         "only div or mod input pattern accepted");
+
+  NoOvfDivModINode* divmod = new NoOvfDivModINode(n->in(0), n->in(1), n->in(2));
+  Node*        dproj  = new ProjNode(divmod, DivModNode::div_proj_num);
+  Node*        mproj  = new ProjNode(divmod, DivModNode::mod_proj_num);
+  return divmod;
+}
+
+//------------------------------make------------------------------------------
+NoOvfDivModLNode* NoOvfDivModLNode::make(Node* div_or_mod) {
+  Node* n = div_or_mod;
+  assert(n->Opcode() == Op_NoOvfDivL || n->Opcode() == Op_NoOvfModL,
+         "only div or mod input pattern accepted");
+
+  NoOvfDivModLNode* divmod = new NoOvfDivModLNode(n->in(0), n->in(1), n->in(2));
+  Node*        dproj  = new ProjNode(divmod, DivModNode::div_proj_num);
+  Node*        mproj  = new ProjNode(divmod, DivModNode::mod_proj_num);
+  return divmod;
+}
diff --git a/src/hotspot/share/opto/divnode.hpp b/src/hotspot/share/opto/divnode.hpp
index d993a2d0bb5..3891e600326 100644
--- a/src/hotspot/share/opto/divnode.hpp
+++ b/src/hotspot/share/opto/divnode.hpp
@@ -103,7 +103,7 @@ public:
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------UDivLNode---------------------------------------
+//------------------------------UDivLNode--------------------------------------
 // Unsigned long division
 class UDivLNode : public Node {
 public:
@@ -116,6 +116,24 @@ public:
   virtual uint ideal_reg() const { return Op_RegL; }
 };
 
+//---------------------------NoOvfDivINode-------------------------------------
+// Non-overflow integer division, UB when dividend == min_jint and divisor == -1
+// so user has to ensure this combination does not appear
+class NoOvfDivINode : public DivINode {
+public:
+  NoOvfDivINode( Node *c, Node *dividend, Node *divisor ) : DivINode(c, dividend, divisor ) {}
+  virtual int Opcode() const;
+};
+
+//---------------------------NoOvfDivLNode-------------------------------------
+// Non-overflow long division, UB when dividend == min_jlong and divisor == -1
+// so user has to ensure this combination does not appear
+class NoOvfDivLNode : public DivLNode {
+public:
+  NoOvfDivLNode( Node *c, Node *dividend, Node *divisor ) : DivLNode(c, dividend, divisor ) {}
+  virtual int Opcode() const;
+};
+
 //------------------------------ModINode---------------------------------------
 // Integer modulus
 class ModINode : public Node {
@@ -162,7 +180,7 @@ public:
   virtual uint ideal_reg() const { return Op_RegD; }
 };
 
-//------------------------------UModINode---------------------------------------
+//------------------------------UModINode--------------------------------------
 // Unsigned integer modulus
 class UModINode : public Node {
 public:
@@ -173,7 +191,7 @@ public:
   virtual uint ideal_reg() const { return Op_RegI; }
 };
 
-//------------------------------UModLNode---------------------------------------
+//------------------------------UModLNode--------------------------------------
 // Unsigned long modulus
 class UModLNode : public Node {
 public:
@@ -184,7 +202,25 @@ public:
   virtual uint ideal_reg() const { return Op_RegL; }
 };
 
-//------------------------------DivModNode---------------------------------------
+//---------------------------NoOvfModINode-------------------------------------
+// Non-overflow integer modulus, UB when dividend == min_jint and divisor == -1
+// so user has to ensure this combination does not appear
+class NoOvfModINode : public ModINode {
+public:
+  NoOvfModINode( Node *c, Node *dividend, Node *divisor ) : ModINode(c, dividend, divisor ) {}
+  virtual int Opcode() const;
+};
+
+//---------------------------NoOvfModLNode-------------------------------------
+// Non-overflow long modulus, UB when dividend == min_jlong and divisor == -1
+// so user has to ensure this combination does not appear
+class NoOvfModLNode : public ModLNode {
+public:
+  NoOvfModLNode( Node *c, Node *dividend, Node *divisor ) : ModLNode(c, dividend, divisor ) {}
+  virtual int Opcode() const;
+};
+
+//-----------------------------DivModNode--------------------------------------
 // Division with remainder result.
 class DivModNode : public MultiNode {
 protected:
@@ -206,7 +242,7 @@ public:
   ProjNode* mod_proj() { return proj_out_or_null(mod_proj_num); }
 };
 
-//------------------------------DivModINode---------------------------------------
+//-----------------------------DivModINode-------------------------------------
 // Integer division with remainder result.
 class DivModINode : public DivModNode {
 public:
@@ -219,7 +255,7 @@ public:
   static DivModINode* make(Node* div_or_mod);
 };
 
-//------------------------------DivModLNode---------------------------------------
+//-----------------------------DivModLNode-------------------------------------
 // Long division with remainder result.
 class DivModLNode : public DivModNode {
 public:
@@ -233,7 +269,7 @@ public:
 };
 
 
-//------------------------------UDivModINode---------------------------------------
+//----------------------------UDivModINode-------------------------------------
 // Unsigend integer division with remainder result.
 class UDivModINode : public DivModNode {
 public:
@@ -246,7 +282,7 @@ public:
   static UDivModINode* make(Node* div_or_mod);
 };
 
-//------------------------------UDivModLNode---------------------------------------
+//----------------------------UDivModLNode-------------------------------------
 // Unsigned long division with remainder result.
 class UDivModLNode : public DivModNode {
 public:
@@ -259,4 +295,28 @@ public:
   static UDivModLNode* make(Node* div_or_mod);
 };
 
+//---------------------------NoOvfDivModINode----------------------------------
+// Non-overflow integer division with remainder result, UB when dividend == min_jint
+// and divisor == -1 so user has to ensure this combination does not appear
+class NoOvfDivModINode : public DivModINode {
+public:
+  NoOvfDivModINode( Node *c, Node *dividend, Node *divisor ) : DivModINode(c, dividend, divisor) {}
+  virtual int Opcode() const;
+
+  // Make a divmod and associated projections from a div or mod.
+  static NoOvfDivModINode* make(Node* div_or_mod);
+};
+
+//---------------------------NoOvfDivModLNode----------------------------------
+// Non-overflow long division with remainder result, UB when dividend == min_jlong
+// and divisor == -1 so user has to ensure this combination does not appear
+class NoOvfDivModLNode : public DivModLNode {
+public:
+  NoOvfDivModLNode( Node *c, Node *dividend, Node *divisor ) : DivModLNode(c, dividend, divisor) {}
+  virtual int Opcode() const;
+
+  // Make a divmod and associated projections from a div or mod.
+  static NoOvfDivModLNode* make(Node* div_or_mod);
+};
+
 #endif // SHARE_OPTO_DIVNODE_HPP
diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp
index 6a4d77479f6..b54752760b0 100644
--- a/src/hotspot/share/opto/parse.hpp
+++ b/src/hotspot/share/opto/parse.hpp
@@ -462,7 +462,8 @@ class Parse : public GraphKit {
   void merge_memory_edges(MergeMemNode* n, int pnum, bool nophi);
 
   // Parse this bytecode, and alter the Parsers JVM->Node mapping
-  void do_one_bytecode();
+  void do_one_bytecode_common();
+  bool do_one_bytecode_targeted();
 
   // helper function to generate array store check
   void array_store_check();
@@ -534,6 +535,10 @@ class Parse : public GraphKit {
   void do_jsr();
   void do_ret();
 
+  // implementation of div/rem bytecodes for handling of special case
+  // min_jint / -1
+  void do_divmod_fixup();
+
   float   dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* test);
   float   branch_prediction(float &cnt, BoolTest::mask btest, int target_bci, Node* test);
   bool    seems_never_taken(float prob) const;
diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp
index 6443657a4f8..836c9a1bea9 100644
--- a/src/hotspot/share/opto/parse1.cpp
+++ b/src/hotspot/share/opto/parse1.cpp
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "jvm_io.h"
 #include "compiler/compileLog.hpp"
 #include "interpreter/linkResolver.hpp"
 #include "memory/resourceArea.hpp"
@@ -1552,7 +1553,22 @@ void Parse::do_one_block() {
     assert(!have_se || pre_bc_sp >= inputs, "have enough stack to execute this BC: pre_bc_sp=%d, inputs=%d", pre_bc_sp, inputs);
 #endif //ASSERT
 
-    do_one_bytecode();
+    // Try parsing machine-dependently, then if it is not needed then parse
+    // the bytecode in a machine independent manner
+    if (!do_one_bytecode_targeted()) {
+      do_one_bytecode_common();
+    }
+#ifndef PRODUCT
+    if (C->should_print_igv(1)) {
+      IdealGraphPrinter* printer = C->igv_printer();
+      char buffer[256];
+      jio_snprintf(buffer, sizeof(buffer), "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
+      bool old = printer->traverse_outs();
+      printer->set_traverse_outs(true);
+      printer->print_method(buffer, 4);
+      printer->set_traverse_outs(old);
+    }
+#endif
 
     assert(!have_se || stopped() || failing() || (sp() - pre_bc_sp) == depth,
            "incorrect depth prediction: sp=%d, pre_bc_sp=%d, depth=%d", sp(), pre_bc_sp, depth);
diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp
index a0e99fb0108..8d00f1ac449 100644
--- a/src/hotspot/share/opto/parse2.cpp
+++ b/src/hotspot/share/opto/parse2.cpp
@@ -1802,7 +1802,7 @@ Node* Parse::optimize_cmp_with_klass(Node* c) {
 
 //------------------------------do_one_bytecode--------------------------------
 // Parse this bytecode, and alter the Parsers JVM->Node mapping
-void Parse::do_one_bytecode() {
+void Parse::do_one_bytecode_common() {
   Node *a, *b, *c, *d;          // Handy temps
   BoolTest::mask btest;
   int i;
@@ -2750,16 +2750,4 @@ void Parse::do_one_bytecode() {
     tty->print("\nUnhandled bytecode %s\n", Bytecodes::name(bc()) );
     ShouldNotReachHere();
   }
-
-#ifndef PRODUCT
-  if (C->should_print_igv(1)) {
-    IdealGraphPrinter* printer = C->igv_printer();
-    char buffer[256];
-    jio_snprintf(buffer, sizeof(buffer), "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
-    bool old = printer->traverse_outs();
-    printer->set_traverse_outs(true);
-    printer->print_method(buffer, 4);
-    printer->set_traverse_outs(old);
-  }
-#endif
 }
diff --git a/src/hotspot/share/opto/parse3.cpp b/src/hotspot/share/opto/parse3.cpp
index a6c1b73ec05..7e0f854436b 100644
--- a/src/hotspot/share/opto/parse3.cpp
+++ b/src/hotspot/share/opto/parse3.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -433,3 +433,77 @@ void Parse::do_multianewarray() {
   // - Make a fast path for small multi-arrays.  (W/ implicit init. loops.)
   // - Issue CastII against length[*] values, to TypeInt::POS.
 }
+
+// On some architectures, a division cannot be done immediately due to
+// the special case with min_jint / -1. As a result, we need to have
+// special handling for this case
+void Parse::do_divmod_fixup() {
+  Bytecodes::Code bc = this->bc();
+  BasicType bt = (bc == Bytecodes::_idiv || bc == Bytecodes::_irem) ? T_INT : T_LONG;
+  // Operands need to stay in the stack during zero check
+  if (bt == T_INT) {
+    zero_check_int(peek(0));
+  } else {
+    zero_check_long(peek(1));
+  }
+  // Compile-time detection of arithmetic exception
+  if (stopped()) {
+    return;
+  }
+
+  Node* in2 = (bt == T_INT) ? pop() : pop_pair();
+  Node* in1 = (bt == T_INT) ? pop() : pop_pair();
+
+  auto generate_division = [](PhaseGVN& gvn, Node* control, Node* in1, Node* in2,
+                              Bytecodes::Code bc) {
+    switch (bc) {
+      case Bytecodes::_idiv: return gvn.transform(new NoOvfDivINode(control, in1, in2));
+      case Bytecodes::_ldiv: return gvn.transform(new NoOvfDivLNode(control, in1, in2));
+      case Bytecodes::_irem: return gvn.transform(new NoOvfModINode(control, in1, in2));
+      case Bytecodes::_lrem: return gvn.transform(new NoOvfModLNode(control, in1, in2));
+      default:
+        ShouldNotReachHere();
+        return static_cast<Node*>(nullptr);
+    }
+  };
+
+  auto push_result = [](Parse& parser, Node* res, BasicType bt) {
+    if (bt == T_INT) {
+      parser.push(res);
+    } else {
+      parser.push_pair(res);
+    }
+  };
+
+  // No overflow possibility here
+  if ((in1 == in2) ||
+      (bt == T_INT  &&  !TypeInt::MIN->higher_equal(_gvn.type(in1))) ||
+      (bt == T_LONG && !TypeLong::MIN->higher_equal(_gvn.type(in1)))) {
+    Node* res = generate_division(_gvn, control(), in1, in2, bc);
+    push_result(*this, res, bt);
+    return;
+  }
+
+  // The generated graph is equivalent to (in2 == -1) ? -in1 : (in1 / in2)
+  // we need to have a separate branch for in2 == -1 due to the special
+  // case of min_jint / -1
+  Node* cmp = _gvn.transform(CmpNode::make(in2, _gvn.integercon(-1, bt), bt));
+  Node* bol = Bool(cmp, BoolTest::eq);
+  IfNode* iff = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
+  Node* iff_true = IfTrue(iff);
+  Node* iff_false = IfFalse(iff);
+  Node* res_fast = (bc == Bytecodes::_idiv || bc == Bytecodes::_ldiv)
+                   ? _gvn.transform(SubNode::make(_gvn.zerocon(bt), in1, bt))
+                   : _gvn.zerocon(bt);
+  Node* res_slow = generate_division(_gvn, iff_false, in1, in2, bc);
+  Node* merge = new RegionNode(3);
+  merge->init_req(1, iff_true);
+  merge->init_req(2, iff_false);
+  record_for_igvn(merge);
+  set_control(_gvn.transform(merge));
+  Node* res = new PhiNode(merge, Type::get_const_basic_type(bt));
+  res->init_req(1, res_fast);
+  res->init_req(2, res_slow);
+  res = _gvn.transform(res);
+  push_result(*this, res, bt);
+}
diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
index d512c993537..eb6bde9d524 100644
--- a/src/hotspot/share/runtime/vmStructs.cpp
+++ b/src/hotspot/share/runtime/vmStructs.cpp
@@ -1581,17 +1581,23 @@
   declare_c2_type(DivDNode, Node)                                         \
   declare_c2_type(UDivINode, Node)                                        \
   declare_c2_type(UDivLNode, Node)                                        \
+  declare_c2_type(NoOvfDivINode, DivINode)                                \
+  declare_c2_type(NoOvfDivLNode, DivLNode)                                \
   declare_c2_type(ModINode, Node)                                         \
   declare_c2_type(ModLNode, Node)                                         \
   declare_c2_type(ModFNode, Node)                                         \
   declare_c2_type(ModDNode, Node)                                         \
   declare_c2_type(UModINode, Node)                                        \
   declare_c2_type(UModLNode, Node)                                        \
+  declare_c2_type(NoOvfModINode, ModINode)                                \
+  declare_c2_type(NoOvfModLNode, ModLNode)                                \
   declare_c2_type(DivModNode, MultiNode)                                  \
   declare_c2_type(DivModINode, DivModNode)                                \
   declare_c2_type(DivModLNode, DivModNode)                                \
   declare_c2_type(UDivModINode, DivModNode)                               \
   declare_c2_type(UDivModLNode, DivModNode)                               \
+  declare_c2_type(NoOvfDivModINode, DivModINode)                          \
+  declare_c2_type(NoOvfDivModLNode, DivModLNode)                          \
   declare_c2_type(BoxLockNode, Node)                                      \
   declare_c2_type(LoopNode, RegionNode)                                   \
   declare_c2_type(CountedLoopNode, LoopNode)                              \
diff --git a/test/hotspot/jtreg/compiler/integerArithmetic/TestDivision.java b/test/hotspot/jtreg/compiler/integerArithmetic/TestDivision.java
new file mode 100644
index 00000000000..4991728c62d
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/integerArithmetic/TestDivision.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.integerArithmetic;
+
+import jdk.test.lib.Asserts;
+
+/*
+ * @test TestDivision
+ * @bug 8284742
+ * @summary Tests to verify compiled code correctly handles integral divisions.
+ * @library /test/lib
+ *
+ * @run main/othervm -Xcomp -XX:-TieredCompilation
+ *      -XX:CompileCommand=compileonly,*.TestDivision::divide
+ *      -XX:CompileCommand=compileonly,*.TestDivision::remainder
+ *      compiler.integerArithmetic.TestDivision
+ */
+public class TestDivision {
+    public static void main(String[] args) {
+        Asserts.assertEquals(divide(19, 7), 19 / 7);
+        Asserts.assertEquals(remainder(19, 7), 19 % 7);
+        Asserts.assertEquals(divide(19L, 7L), 19L / 7L);
+        Asserts.assertEquals(remainder(19L, 7L), 19L % 7L);
+
+        Asserts.assertEquals(divide(19, -7), 19 / -7);
+        Asserts.assertEquals(remainder(19, -7), 19 % -7);
+        Asserts.assertEquals(divide(19L, -7L), 19L / -7L);
+        Asserts.assertEquals(remainder(19L, -7L), 19L % -7L);
+
+        Asserts.assertEquals(divide(-19, 7), -19 / 7);
+        Asserts.assertEquals(remainder(-19, 7), -19 % 7);
+        Asserts.assertEquals(divide(-19L, 7L), -19L / 7L);
+        Asserts.assertEquals(remainder(-19L, 7L), -19L % 7L);
+
+        Asserts.assertEquals(divide(-19, -7), -19 / -7);
+        Asserts.assertEquals(remainder(-19, -7), -19 % -7);
+        Asserts.assertEquals(divide(-19L, -7L), -19L / -7L);
+        Asserts.assertEquals(remainder(-19L, -7L), -19L % -7L);
+
+        Asserts.assertEquals(divide(Integer.MIN_VALUE, -1), Integer.MIN_VALUE / -1);
+        Asserts.assertEquals(remainder(Integer.MIN_VALUE, -1), Integer.MIN_VALUE % -1);
+        Asserts.assertEquals(divide(Long.MIN_VALUE, -1), Long.MIN_VALUE / -1L);
+        Asserts.assertEquals(remainder(Long.MIN_VALUE, -1), Long.MIN_VALUE % -1L);
+
+        try {
+            divide(19, 0);
+            Asserts.fail();
+        } catch (ArithmeticException e) {}
+        try {
+            remainder(19, 0);
+            Asserts.fail();
+        } catch (ArithmeticException e) {}
+        try {
+            divide(19L, 0L);
+            Asserts.fail();
+        } catch (ArithmeticException e) {}
+        try {
+            remainder(19L, 0L);
+            Asserts.fail();
+        } catch (ArithmeticException e) {}
+    }
+
+    static int divide(int x, int y) {
+        return x / y;
+    }
+
+    static int remainder(int x, int y) {
+        return x % y;
+    }
+
+    static long divide(long x, long y) {
+        return x / y;
+    }
+
+    static long remainder(long x, long y) {
+        return x % y;
+    }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
index 27c358abe69..166127784cf 100644
--- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
+++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java
@@ -169,8 +169,8 @@ public class IRNode {
     public static final String MUL = START + "Mul(I|L|F|D)" + MID + END;
     public static final String MUL_I = START + "MulI" + MID + END;
     public static final String MUL_L = START + "MulL" + MID + END;
-    public static final String DIV = START + "Div(I|L|F|D)" + MID + END;
-    public static final String DIV_L = START + "DivL" + MID + END;
+    public static final String DIV = START + "(NoOvf)?Div(I|L|F|D)" + MID + END;
+    public static final String DIV_L = START + "(NoOvf)?DivL" + MID + END;
     public static final String CON_I = START + "ConI" + MID + END;
     public static final String CON_L = START + "ConL" + MID + END;
     public static final String CONV_I2L = START + "ConvI2L" + MID + END;
diff --git a/test/micro/org/openjdk/bench/java/lang/IntegerDivMod.java b/test/micro/org/openjdk/bench/java/lang/IntegerDivMod.java
index 7ef6f2d043a..0cf4439a9aa 100644
--- a/test/micro/org/openjdk/bench/java/lang/IntegerDivMod.java
+++ b/test/micro/org/openjdk/bench/java/lang/IntegerDivMod.java
@@ -24,6 +24,7 @@ package org.openjdk.bench.java.lang;
 
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.annotations.OutputTimeUnit;
 import org.openjdk.jmh.annotations.Scope;
@@ -34,12 +35,10 @@ import java.util.random.RandomGenerator;
 import java.util.random.RandomGeneratorFactory;
 import java.util.concurrent.TimeUnit;
 
-/**
- * Tests unsigned division and modulus methods in java.lang.Integer
- */
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.NANOSECONDS)
 @State(Scope.Thread)
+@Fork(1)
 public class IntegerDivMod {
 
     RandomGenerator randomGenerator;
@@ -60,12 +59,37 @@ public class IntegerDivMod {
         for (int i = 0; i < BUFFER_SIZE; i++) {
             dividends[i] = rng.nextInt();
             int divisor = rng.nextInt();
-            if (divisorType.equals("positive")) divisor = Math.abs(divisor);
-            else if (divisorType.equals("negative")) divisor = -Math.abs(divisor);
+            if (divisorType.equals("positive")) {
+                divisor = Math.abs(divisor);
+            } else if (divisorType.equals("negative")) {
+                divisor = -Math.abs(divisor);
+            }
             divisors[i] = divisor;
         }
     }
 
+    @Benchmark
+    public void testDivide() {
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / divisors[i];
+        }
+    }
+
+    @Benchmark
+    public void testDivideKnownPositive() {
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / Math.max(1, divisors[i]);
+        }
+    }
+
+    @Benchmark
+    public void testDivideHoistedDivisor() {
+        int x = divisors[0];
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / x;
+        }
+    }
+
     @Benchmark
     public void testDivideUnsigned() {
         for (int i = 0; i < BUFFER_SIZE; i++) {
@@ -91,8 +115,4 @@ public class IntegerDivMod {
         quotients[i] = Integer.divideUnsigned(dividend, divisor);
         remainders[i] = Integer.remainderUnsigned(dividend, divisor);
     }
-
 }
-
-
-
diff --git a/test/micro/org/openjdk/bench/java/lang/LongDivMod.java b/test/micro/org/openjdk/bench/java/lang/LongDivMod.java
index 38f40bbff27..63f15fdc244 100644
--- a/test/micro/org/openjdk/bench/java/lang/LongDivMod.java
+++ b/test/micro/org/openjdk/bench/java/lang/LongDivMod.java
@@ -24,6 +24,7 @@ package org.openjdk.bench.java.lang;
 
 import org.openjdk.jmh.annotations.Benchmark;
 import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Fork;
 import org.openjdk.jmh.annotations.Mode;
 import org.openjdk.jmh.annotations.OutputTimeUnit;
 import org.openjdk.jmh.annotations.Scope;
@@ -34,12 +35,10 @@ import java.util.random.RandomGenerator;
 import java.util.random.RandomGeneratorFactory;
 import java.util.concurrent.TimeUnit;
 
-/**
- * Tests unsigned division and modulus methods in java.lang.Long
- */
 @BenchmarkMode(Mode.AverageTime)
 @OutputTimeUnit(TimeUnit.NANOSECONDS)
 @State(Scope.Thread)
+@Fork(1)
 public class LongDivMod {
 
     RandomGenerator randomGenerator;
@@ -60,12 +59,37 @@ public class LongDivMod {
         for (int i = 0; i < BUFFER_SIZE; i++) {
             dividends[i] = rng.nextLong();
             long divisor = rng.nextLong();
-            if (divisorType.equals("positive")) divisor = Math.abs(divisor);
-            else if (divisorType.equals("negative")) divisor = -Math.abs(divisor);
+            if (divisorType.equals("positive")) {
+                divisor = Math.abs(divisor);
+            } else if (divisorType.equals("negative")) {
+                divisor = -Math.abs(divisor);
+            }
             divisors[i] = divisor;
         }
     }
 
+    @Benchmark
+    public void testDivide() {
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / divisors[i];
+        }
+    }
+
+    @Benchmark
+    public void testDivideKnownPositive() {
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / Math.max(1, divisors[i]);
+        }
+    }
+
+    @Benchmark
+    public void testDivideHoistedDivisor() {
+        long x = divisors[0];
+        for (int i = 0; i < BUFFER_SIZE; i++) {
+            quotients[i] = dividends[i] / x;
+        }
+    }
+
     @Benchmark
     public void testDivideUnsigned() {
         for (int i = 0; i < BUFFER_SIZE; i++) {
@@ -91,8 +115,4 @@ public class LongDivMod {
         quotients[i] = Long.divideUnsigned(dividend, divisor);
         remainders[i] = Long.remainderUnsigned(dividend, divisor);
     }
-
 }
-
-
-