Skip to content

8352423: RISC-V: simplify DivI/L ModI/L #24119

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/hotspot/cpu/riscv/c1_LIRAssembler_arith_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right,
}
} else {
Register rreg = right->as_register();
__ corrected_idivl(dreg, lreg, rreg, is_irem, /* is_signed */ true);
if (is_irem) {
__ remw(dreg, lreg, rreg);
} else {
__ divw(dreg, lreg, rreg);
}
}
}

Expand Down Expand Up @@ -171,12 +175,8 @@ void LIR_Assembler::arith_op_double_cpu(LIR_Code code, LIR_Opr left, LIR_Opr rig
case lir_add: __ add(dest->as_register_lo(), lreg_lo, rreg_lo); break;
case lir_sub: __ sub(dest->as_register_lo(), lreg_lo, rreg_lo); break;
case lir_mul: __ mul(dest->as_register_lo(), lreg_lo, rreg_lo); break;
case lir_div: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo,
/* want_remainder */ false, /* is_signed */ true);
break;
case lir_rem: __ corrected_idivq(dest->as_register_lo(), lreg_lo, rreg_lo,
/* want_remainder */ true, /* is_signed */ true);
break;
case lir_div: __ div(dest->as_register_lo(), lreg_lo, rreg_lo); break;
case lir_rem: __ rem(dest->as_register_lo(), lreg_lo, rreg_lo); break;
default:
ShouldNotReachHere();
}
Expand Down
65 changes: 0 additions & 65 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3346,71 +3346,6 @@ void MacroAssembler::store_heap_oop_null(Address dst) {
access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg, noreg);
}

int MacroAssembler::corrected_idivl(Register result, Register rs1, Register rs2,
bool want_remainder, bool is_signed)
{
// Full implementation of Java idiv and irem. The function
// returns the (pc) offset of the div instruction - may be needed
// for implicit exceptions.
//
// input : rs1: dividend
// rs2: divisor
//
// result: either
// quotient (= rs1 idiv rs2)
// remainder (= rs1 irem rs2)


int idivl_offset = offset();
if (!want_remainder) {
if (is_signed) {
divw(result, rs1, rs2);
} else {
divuw(result, rs1, rs2);
}
} else {
// result = rs1 % rs2;
if (is_signed) {
remw(result, rs1, rs2);
} else {
remuw(result, rs1, rs2);
}
}
return idivl_offset;
}

int MacroAssembler::corrected_idivq(Register result, Register rs1, Register rs2,
bool want_remainder, bool is_signed)
{
// Full implementation of Java ldiv and lrem. The function
// returns the (pc) offset of the div instruction - may be needed
// for implicit exceptions.
//
// input : rs1: dividend
// rs2: divisor
//
// result: either
// quotient (= rs1 idiv rs2)
// remainder (= rs1 irem rs2)

int idivq_offset = offset();
if (!want_remainder) {
if (is_signed) {
div(result, rs1, rs2);
} else {
divu(result, rs1, rs2);
}
} else {
// result = rs1 % rs2;
if (is_signed) {
rem(result, rs1, rs2);
} else {
remu(result, rs1, rs2);
}
}
return idivq_offset;
}

// Look up the method for a megamorphic invokeinterface call.
// The target method is determined by <intf_klass, itable_index>.
// The receiver klass is in recv_klass.
Expand Down
6 changes: 0 additions & 6 deletions src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,6 @@ class MacroAssembler: public Assembler {
static bool needs_explicit_null_check(intptr_t offset);
static bool uses_implicit_null_check(void* address);

// idiv variant which deals with MINLONG as dividend and -1 as divisor
int corrected_idivl(Register result, Register rs1, Register rs2,
bool want_remainder, bool is_signed);
int corrected_idivq(Register result, Register rs1, Register rs2,
bool want_remainder, bool is_signed);

// interface method calling
void lookup_interface_method(Register recv_klass,
Register intf_klass,
Expand Down
90 changes: 24 additions & 66 deletions src/hotspot/cpu/riscv/riscv.ad
Original file line number Diff line number Diff line change
Expand Up @@ -2485,64 +2485,6 @@ encode %{
}
%}

// arithmetic encodings

enc_class riscv_enc_divw(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivl(dst_reg, src1_reg, src2_reg, /* want_remainder */ false, /* is_signed */ true);
%}

enc_class riscv_enc_divuw(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivl(dst_reg, src1_reg, src2_reg, /* want_remainder */ false, /* is_signed */ false);
%}

enc_class riscv_enc_div(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivq(dst_reg, src1_reg, src2_reg, /* want_remainder */ false, /* is_signed */ true);
%}

enc_class riscv_enc_divu(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivq(dst_reg, src1_reg, src2_reg, /* want_remainder */ false, /* is_signed */ false);
%}

enc_class riscv_enc_modw(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivl(dst_reg, src1_reg, src2_reg, /* want_remainder */ true, /* is_signed */ true);
%}

enc_class riscv_enc_moduw(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivl(dst_reg, src1_reg, src2_reg, /* want_remainder */ true, /* is_signed */ false);
%}

enc_class riscv_enc_mod(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivq(dst_reg, src1_reg, src2_reg, /* want_remainder */ true, /* is_signed */ true);
%}

enc_class riscv_enc_modu(iRegI dst, iRegI src1, iRegI src2) %{
Register dst_reg = as_Register($dst$$reg);
Register src1_reg = as_Register($src1$$reg);
Register src2_reg = as_Register($src2$$reg);
__ corrected_idivq(dst_reg, src1_reg, src2_reg, /* want_remainder */ true, /* is_signed */ false);
%}

enc_class riscv_enc_tail_call(iRegP jump_target) %{
Register target_reg = as_Register($jump_target$$reg);
__ jr(target_reg);
Expand Down Expand Up @@ -6763,7 +6705,9 @@ instruct divI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
ins_cost(IDIVSI_COST);
format %{ "divw $dst, $src1, $src2\t#@divI"%}

ins_encode(riscv_enc_divw(dst, src1, src2));
ins_encode %{
__ divw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(idiv_reg_reg);
%}

Expand All @@ -6772,7 +6716,9 @@ instruct UdivI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
ins_cost(IDIVSI_COST);
format %{ "divuw $dst, $src1, $src2\t#@UdivI"%}

ins_encode(riscv_enc_divuw(dst, src1, src2));
ins_encode %{
__ divuw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(idiv_reg_reg);
%}

Expand All @@ -6794,7 +6740,9 @@ instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
ins_cost(IDIVDI_COST);
format %{ "div $dst, $src1, $src2\t#@divL" %}

ins_encode(riscv_enc_div(dst, src1, src2));
ins_encode %{
__ div(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ldiv_reg_reg);
%}

Expand All @@ -6804,7 +6752,9 @@ instruct UdivL(iRegLNoSp dst, iRegL src1, iRegL src2) %{

format %{ "divu $dst, $src1, $src2\t#@UdivL" %}

ins_encode(riscv_enc_divu(dst, src1, src2));
ins_encode %{
__ divu(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ldiv_reg_reg);
%}

Expand All @@ -6826,7 +6776,9 @@ instruct modI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
ins_cost(IDIVSI_COST);
format %{ "remw $dst, $src1, $src2\t#@modI" %}

ins_encode(riscv_enc_modw(dst, src1, src2));
ins_encode %{
__ remw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ialu_reg_reg);
%}

Expand All @@ -6835,7 +6787,9 @@ instruct UmodI(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %{
ins_cost(IDIVSI_COST);
format %{ "remuw $dst, $src1, $src2\t#@UmodI" %}

ins_encode(riscv_enc_moduw(dst, src1, src2));
ins_encode %{
__ remuw(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ialu_reg_reg);
%}

Expand All @@ -6846,7 +6800,9 @@ instruct modL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
ins_cost(IDIVDI_COST);
format %{ "rem $dst, $src1, $src2\t#@modL" %}

ins_encode(riscv_enc_mod(dst, src1, src2));
ins_encode %{
__ rem(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ialu_reg_reg);
%}

Expand All @@ -6855,7 +6811,9 @@ instruct UmodL(iRegLNoSp dst, iRegL src1, iRegL src2) %{
ins_cost(IDIVDI_COST);
format %{ "remu $dst, $src1, $src2\t#@UmodL" %}

ins_encode(riscv_enc_modu(dst, src1, src2));
ins_encode %{
__ remu(as_Register($dst$$reg), as_Register($src1$$reg), as_Register($src2$$reg));
%}
ins_pipe(ialu_reg_reg);
%}

Expand Down
8 changes: 4 additions & 4 deletions src/hotspot/cpu/riscv/templateTable_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,7 @@ void TemplateTable::idiv() {
__ bind(no_div0);
__ pop_i(x11);
// x10 <== x11 idiv x10
__ corrected_idivl(x10, x11, x10, /* want_remainder */ false, /* is_signed */ true);
__ divw(x10, x11, x10);
}

void TemplateTable::irem() {
Expand All @@ -1337,7 +1337,7 @@ void TemplateTable::irem() {
__ bind(no_div0);
__ pop_i(x11);
// x10 <== x11 irem x10
__ corrected_idivl(x10, x11, x10, /* want_remainder */ true, /* is_signed */ true);
__ remw(x10, x11, x10);
}

void TemplateTable::lmul() {
Expand All @@ -1356,7 +1356,7 @@ void TemplateTable::ldiv() {
__ bind(no_div0);
__ pop_l(x11);
// x10 <== x11 ldiv x10
__ corrected_idivq(x10, x11, x10, /* want_remainder */ false, /* is_signed */ true);
__ div(x10, x11, x10);
}

void TemplateTable::lrem() {
Expand All @@ -1369,7 +1369,7 @@ void TemplateTable::lrem() {
__ bind(no_div0);
__ pop_l(x11);
// x10 <== x11 lrem x10
__ corrected_idivq(x10, x11, x10, /* want_remainder */ true, /* is_signed */ true);
__ rem(x10, x11, x10);
}

void TemplateTable::lshl() {
Expand Down
10 changes: 5 additions & 5 deletions test/hotspot/jtreg/compiler/c2/TestDivModNodes.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024 Red Hat and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Red Hat 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
Expand Down Expand Up @@ -68,7 +68,7 @@ private static long nextNonZeroLong() {
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"},
counts = {IRNode.DIV_MOD_I, "1"},
failOn = {IRNode.DIV_I, IRNode.MOD_I})
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"},
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatformOr = {"aarch64", "true", "riscv64", "true"},
counts = {IRNode.DIV_I, "1", IRNode.MUL_I, "1", IRNode.SUB_I, "1"},
failOn = {IRNode.MOD_I})
@IR(applyIf = {"UseDivMod", "false"},
Expand All @@ -94,7 +94,7 @@ private static void runSignedIntDivMod() {
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"},
counts = {IRNode.DIV_MOD_L, "1"},
failOn = {IRNode.DIV_L, IRNode.MOD_L})
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"},
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatformOr = {"aarch64", "true", "riscv64", "true"},
counts = {IRNode.DIV_L, "1", IRNode.MUL_L, "1", IRNode.SUB_L, "1"},
failOn = {IRNode.MOD_L})
@IR(applyIf = {"UseDivMod", "false"},
Expand All @@ -119,7 +119,7 @@ private static void runSignedLongDivMod() {
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"},
counts = {IRNode.UDIV_MOD_I, "1"},
failOn = {IRNode.UDIV_I, IRNode.UMOD_I})
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"},
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatformOr = {"aarch64", "true", "riscv64", "true"},
counts = {IRNode.UDIV_I, "1", IRNode.MUL_I, "1", IRNode.SUB_I, "1"},
failOn = {IRNode.UMOD_I})
@IR(applyIf = {"UseDivMod", "false"},
Expand All @@ -144,7 +144,7 @@ private static void runUnsignedIntDivMod() {
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"x64", "true"},
counts = {IRNode.UDIV_MOD_L, "1"},
failOn = {IRNode.UDIV_L, IRNode.UMOD_L})
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatform = {"aarch64", "true"},
@IR(applyIf = {"UseDivMod", "true"}, applyIfPlatformOr = {"aarch64", "true", "riscv64", "true"},
counts = {IRNode.UDIV_L, "1", IRNode.MUL_L, "1", IRNode.SUB_L, "1"},
failOn = {IRNode.MOD_L})
@IR(applyIf = {"UseDivMod", "false"},
Expand Down