diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 2f2bee6e22f0f..e9d25dba9b51b 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2321,6 +2321,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return true; +} + // Is this branch offset short enough that a short branch can be used? // // NOTE: If the platform does not provide any short branch variants, then @@ -7906,31 +7910,31 @@ instruct membar_volatile() %{ instruct castX2P(iRegPNoSp dst, iRegL src) %{ match(Set dst (CastX2P src)); + // We still assign cost here because two-address instructions may bring + // side impact, i.e., spilling. ins_cost(INSN_COST); - format %{ "mov $dst, $src\t# long -> ptr" %} - + format %{ "castX2P $src\t# long -> ptr" %} + size(0); ins_encode %{ - if ($dst$$reg != $src$$reg) { - __ mov(as_Register($dst$$reg), as_Register($src$$reg)); - } + /* empty encoding */ + assert($dst$$reg == $src$$reg, "We can't remove it when dst != src"); %} - - ins_pipe(ialu_reg); + ins_pipe(pipe_class_empty); %} instruct castP2X(iRegLNoSp dst, iRegP src) %{ match(Set dst (CastP2X src)); + // We still assign cost here because two-address instructions may bring + // side impact, i.e., spilling. ins_cost(INSN_COST); - format %{ "mov $dst, $src\t# ptr -> long" %} - + format %{ "castP2X $src\t# ptr -> long" %} + size(0); ins_encode %{ - if ($dst$$reg != $src$$reg) { - __ mov(as_Register($dst$$reg), as_Register($src$$reg)); - } + /* empty encoding */ + assert($dst$$reg == $src$$reg, "We can't remove it when dst != src"); %} - - ins_pipe(ialu_reg); + ins_pipe(pipe_class_empty); %} // Convert oop into int for vectors alignment masking diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 638c48ad5aa31..c977af5b700fb 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1017,6 +1017,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + // Vector width in bytes int Matcher::vector_width_in_bytes(BasicType bt) { return MaxVectorSize; diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 38485da958132..7a0a5425c35b8 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2164,6 +2164,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + // Vector width in bytes. int Matcher::vector_width_in_bytes(BasicType bt) { if (SuperwordUseVSX) { diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index e2a1fcf621fab..0e7dc24b85be4 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1958,6 +1958,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + // Is this branch offset short enough that a short branch can be used? // // NOTE: If the platform does not provide any short branch variants, then diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 0fe3840b9b53c..144db49a706b8 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1489,6 +1489,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + //----------SUPERWORD HELPERS---------------------------------------- // Vector width in bytes. diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 49a3cad37df2f..9652bc3a83448 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -1398,6 +1398,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(0, 0); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + // Is this branch offset short enough that a short branch can be used? // // NOTE: If the platform does not provide any short branch variants, then diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 1490cfa60b34f..a0e7ffe27d136 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1597,6 +1597,10 @@ OptoRegPair Matcher::vector_return_value(uint ideal_reg) { return OptoRegPair(hi, lo); } +bool Matcher::use_same_src_and_dest_reg_for_CastX2P(void) { + return false; +} + // Is this branch offset short enough that a short branch can be used? // // NOTE: If the platform does not provide any short branch variants, then diff --git a/src/hotspot/share/adlc/output_h.cpp b/src/hotspot/share/adlc/output_h.cpp index 9d54d8406887f..92fbcf6cce520 100644 --- a/src/hotspot/share/adlc/output_h.cpp +++ b/src/hotspot/share/adlc/output_h.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -1688,6 +1688,19 @@ void ArchDesc::declareClasses(FILE *fp) { // Identify which input register matches the input register. uint matching_input = instr->two_address(_globalNames); + // Allocate the same src and dest register for CastX2P and CastP2X + // on some target platforms, then we can remove the instructions in + // the final assembly. + if (strcmp("CastX2P", instr->ideal_Opcode(_globalNames)) == 0 || + strcmp("CastP2X", instr->ideal_Opcode(_globalNames)) == 0) { + assert(matching_input == 0, ""); + fprintf(fp," virtual uint two_adr() const {\n"); + fprintf(fp," if (Matcher::use_same_src_and_dest_reg_for_CastX2P())\n"); + fprintf(fp," return oper_input_base();\n"); + fprintf(fp," return 0;\n"); + fprintf(fp," }\n"); + } + // Generate the method if it returns != 0 otherwise use MachNode::two_adr() if( matching_input != 0 ) { fprintf(fp," virtual uint two_adr() const "); diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 84e48086f92d3..c514ec72a2b6e 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -456,6 +456,10 @@ class Matcher : public PhaseTransform { static bool supports_vector_calling_convention(); static OptoRegPair vector_return_value(uint ideal_reg); + // Is it preferred to use the same src and dest register for CastX2P and + // CastP2X? If true, we can remove the instructions in the final assembly. + static bool use_same_src_and_dest_reg_for_CastX2P(); + // Is this branch offset small enough to be addressed by a short branch? bool is_short_branch_offset(int rule, int br_size, int offset);