@@ -8848,10 +8848,26 @@ instruct mulL_reg_imm16(iRegLdst dst, iRegLsrc src1, immL16 src2) %{
88488848 ins_pipe(pipe_class_default);
88498849%}
88508850
8851- // Integer Division, but not min_jint / -1
8852- instruct noOvfDivI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
8853- match(Set dst (NoOvfDivI src1 src2));
8854- ins_cost(3*DEFAULT_COST);
8851+ // Integer Division with Immediate -1: Negate.
8852+ instruct divI_reg_immIvalueMinus1(iRegIdst dst, iRegIsrc src1, immI_minus1 src2) %{
8853+ match(Set dst (DivI src1 src2));
8854+ ins_cost(DEFAULT_COST);
8855+
8856+ format %{ "NEG $dst, $src1 \t// /-1" %}
8857+ size(4);
8858+ ins_encode %{
8859+ __ neg($dst$$Register, $src1$$Register);
8860+ %}
8861+ ins_pipe(pipe_class_default);
8862+ %}
8863+
8864+ // Integer Division with constant, but not -1.
8865+ // We should be able to improve this by checking the type of src2.
8866+ // It might well be that src2 is known to be positive.
8867+ instruct divI_reg_regnotMinus1(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
8868+ match(Set dst (DivI src1 src2));
8869+ predicate(n->in(2)->find_int_con(-1) != -1); // src2 is a constant, but not -1
8870+ ins_cost(2*DEFAULT_COST);
88558871
88568872 format %{ "DIVW $dst, $src1, $src2 \t// /not-1" %}
88578873 size(4);
@@ -8861,10 +8877,56 @@ instruct noOvfDivI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
88618877 ins_pipe(pipe_class_default);
88628878%}
88638879
8864- // Long Division, but not min_jlong / -1
8865- instruct noOvfDivL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
8866- match(Set dst (NoOvfDivL src1 src2));
8867- ins_cost(3*DEFAULT_COST);
8880+ instruct cmovI_bne_negI_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src1) %{
8881+ effect(USE_DEF dst, USE src1, USE crx);
8882+ predicate(false);
8883+
8884+ ins_variable_size_depending_on_alignment(true);
8885+
8886+ format %{ "CMOVE $dst, neg($src1), $crx" %}
8887+ // Worst case is branch + move + stop, no stop without scheduler.
8888+ size(8);
8889+ ins_encode %{
8890+ Label done;
8891+ __ bne($crx$$CondRegister, done);
8892+ __ neg($dst$$Register, $src1$$Register);
8893+ __ bind(done);
8894+ %}
8895+ ins_pipe(pipe_class_default);
8896+ %}
8897+
8898+ // Integer Division with Registers not containing constants.
8899+ instruct divI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
8900+ match(Set dst (DivI src1 src2));
8901+ ins_cost(10*DEFAULT_COST);
8902+
8903+ expand %{
8904+ immI16 imm %{ (int)-1 %}
8905+ flagsReg tmp1;
8906+ cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1
8907+ divI_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2
8908+ cmovI_bne_negI_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1
8909+ %}
8910+ %}
8911+
8912+ // Long Division with Immediate -1: Negate.
8913+ instruct divL_reg_immLvalueMinus1(iRegLdst dst, iRegLsrc src1, immL_minus1 src2) %{
8914+ match(Set dst (DivL src1 src2));
8915+ ins_cost(DEFAULT_COST);
8916+
8917+ format %{ "NEG $dst, $src1 \t// /-1, long" %}
8918+ size(4);
8919+ ins_encode %{
8920+ __ neg($dst$$Register, $src1$$Register);
8921+ %}
8922+ ins_pipe(pipe_class_default);
8923+ %}
8924+
8925+ // Long Division with constant, but not -1.
8926+ instruct divL_reg_regnotMinus1(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
8927+ match(Set dst (DivL src1 src2));
8928+ predicate(n->in(2)->find_long_con(-1L) != -1L); // Src2 is a constant, but not -1.
8929+ ins_cost(2*DEFAULT_COST);
88688930
88698931 format %{ "DIVD $dst, $src1, $src2 \t// /not-1, long" %}
88708932 size(4);
@@ -8874,31 +8936,71 @@ instruct noOvfDivL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
88748936 ins_pipe(pipe_class_default);
88758937%}
88768938
8939+ instruct cmovL_bne_negL_reg(iRegLdst dst, flagsRegSrc crx, iRegLsrc src1) %{
8940+ effect(USE_DEF dst, USE src1, USE crx);
8941+ predicate(false);
8942+
8943+ ins_variable_size_depending_on_alignment(true);
8944+
8945+ format %{ "CMOVE $dst, neg($src1), $crx" %}
8946+ // Worst case is branch + move + stop, no stop without scheduler.
8947+ size(8);
8948+ ins_encode %{
8949+ Label done;
8950+ __ bne($crx$$CondRegister, done);
8951+ __ neg($dst$$Register, $src1$$Register);
8952+ __ bind(done);
8953+ %}
8954+ ins_pipe(pipe_class_default);
8955+ %}
8956+
8957+ // Long Division with Registers not containing constants.
8958+ instruct divL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
8959+ match(Set dst (DivL src1 src2));
8960+ ins_cost(10*DEFAULT_COST);
8961+
8962+ expand %{
8963+ immL16 imm %{ (int)-1 %}
8964+ flagsReg tmp1;
8965+ cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1
8966+ divL_reg_regnotMinus1(dst, src1, src2); // dst = src1 / src2
8967+ cmovL_bne_negL_reg(dst, tmp1, src1); // cmove dst = neg(src1) if src2 == -1
8968+ %}
8969+ %}
8970+
88778971// Integer Remainder with registers.
88788972instruct modI_reg_reg_Ex(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
8879- match(Set dst (NoOvfModI src1 src2));
8880- ins_cost(5 *DEFAULT_COST);
8973+ match(Set dst (ModI src1 src2));
8974+ ins_cost(10 *DEFAULT_COST);
88818975
88828976 expand %{
8883- iRegIdst tmp1;
8977+ immI16 imm %{ (int)-1 %}
8978+ flagsReg tmp1;
88848979 iRegIdst tmp2;
8885- noOvfDivI_reg_reg(tmp1, src1, src2);
8886- mulI_reg_reg(tmp2, src2, tmp1);
8887- subI_reg_reg(dst, src1, tmp2);
8980+ iRegIdst tmp3;
8981+ cmpI_reg_imm16(tmp1, src2, imm); // check src2 == -1
8982+ divI_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
8983+ cmovI_bne_negI_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1
8984+ mulI_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2
8985+ subI_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3
88888986 %}
88898987%}
88908988
88918989// Long Remainder with registers
88928990instruct modL_reg_reg_Ex(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
8893- match(Set dst (NoOvfModL src1 src2));
8894- ins_cost(5 *DEFAULT_COST);
8991+ match(Set dst (ModL src1 src2));
8992+ ins_cost(10 *DEFAULT_COST);
88958993
88968994 expand %{
8897- iRegLdst tmp1;
8995+ immL16 imm %{ (int)-1 %}
8996+ flagsReg tmp1;
88988997 iRegLdst tmp2;
8899- noOvfDivL_reg_reg(tmp1, src1, src2);
8900- mulL_reg_reg(tmp2, src2, tmp1);
8901- subL_reg_reg(dst, src1, tmp2);
8998+ iRegLdst tmp3;
8999+ cmpL_reg_imm16(tmp1, src2, imm); // check src2 == -1
9000+ divL_reg_regnotMinus1(tmp2, src1, src2); // tmp2 = src1 / src2
9001+ cmovL_bne_negL_reg(tmp2, tmp1, src1); // cmove tmp2 = neg(src1) if src2 == -1
9002+ mulL_reg_reg(tmp3, src2, tmp2); // tmp3 = src2 * tmp2
9003+ subL_reg_reg(dst, src1, tmp3); // dst = src1 - tmp3
89029004 %}
89039005%}
89049006
0 commit comments