From 8bae9122ab3751a4a0cf371262760d00803d47b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarre=C3=B1o?= Date: Thu, 24 Jul 2025 15:31:38 +0100 Subject: [PATCH 1/2] Branch instead of CMov: Intrinsic --- src/hotspot/cpu/aarch64/aarch64.ad | 33 ++++++++++++++++++++++++++++++ src/hotspot/cpu/x86/x86_64.ad | 32 +++++++++++++++++++++++++++++ src/hotspot/share/opto/addnode.cpp | 3 ++- src/hotspot/share/opto/addnode.hpp | 8 ++++---- src/hotspot/share/opto/macro.cpp | 30 ++++++++++++++------------- 5 files changed, 87 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 1b128f2a0ce..680de3af793 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -15770,6 +15770,39 @@ instruct maxI_reg_reg(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2) %} %} +instruct maxL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) +%{ + match(Set dst (MaxL src1 src2)); + effect(TEMP_DEF dst); + ins_cost(INSN_COST * 3); + + ins_encode %{ + Label done; + __ mov(as_Register($dst$$reg), as_Register($src2$$reg)); // dst = src2 (b) + __ cmp(as_Register($src2$$reg), as_Register($src1$$reg)); // src1 (b) > src2 (a) ? + __ br(Assembler::GT, done); + __ mov(as_Register($dst$$reg), as_Register($src1$$reg)); // dst = src1 (a) + __ bind(done); + %} + ins_pipe(pipe_cmp_branch); +%} + +instruct minL_reg_reg(iRegLNoSp dst, iRegL src1, iRegL src2) +%{ + match(Set dst (MinL src1 src2)); + effect(TEMP_DEF dst); + ins_cost(INSN_COST * 3); + + ins_encode %{ + Label done; + __ mov(as_Register($dst$$reg), as_Register($src2$$reg)); // dst = src2 (b) + __ cmp(as_Register($src2$$reg), as_Register($src1$$reg)); // src2 (b) < src1 (a) ? + __ br(Assembler::LT, done); + __ mov(as_Register($dst$$reg), as_Register($src1$$reg)); // dst = src1 (a) + __ bind(done); + %} + ins_pipe(pipe_cmp_branch); +%} // ============================================================================ // Branch Instructions diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 751e9bda513..5ecbf3fe549 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -13821,6 +13821,38 @@ instruct maxI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2) %} %} +instruct maxL_rReg(rRegL dst, rRegL src, rFlagsReg cr) +%{ + match(Set dst (MaxL src dst)); + effect(KILL cr); + + ins_cost(200); + ins_encode %{ + Label done; + __ cmpq($dst$$Register, $src$$Register); + __ jccb(Assembler::greater, done); // dst (b) > src (a) ? + __ movq($dst$$Register, $src$$Register); // dst = src (a) + __ bind(done); + %} + ins_pipe(pipe_cmov_reg); +%} + +instruct minL_rReg(rRegL dst, rRegL src, rFlagsReg cr) +%{ + match(Set dst (MinL src dst)); + effect(KILL cr); + + ins_cost(200); + ins_encode %{ + Label done; + __ cmpq($dst$$Register, $src$$Register); + __ jccb(Assembler::less, done); // dst (b) < src (a) ? + __ movq($dst$$Register, $src$$Register); // dst = src (a) + __ bind(done); + %} + ins_pipe(pipe_cmov_reg); +%} + // ============================================================================ // Branch Instructions diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 143398c57d0..102125661d1 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -136,7 +136,8 @@ Node *AddNode::Ideal(PhaseGVN *phase, bool can_reshape) { bool con_right = t2->singleton(); // Check for commutative operation desired - if (commute(phase, this)) return this; + // todo temporarily remove commuting until branching is right + // if (commute(phase, this)) return this; AddNode *progress = nullptr; // Progress flag diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 456a8d9f9a0..4e0f033bf26 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -357,8 +357,8 @@ class MinINode : public MaxNode { class MaxLNode : public MaxNode { public: MaxLNode(Compile* C, Node* in1, Node* in2) : MaxNode(in1, in2) { - init_flags(Flag_is_macro); - C->add_macro_node(this); + // init_flags(Flag_is_macro); + // C->add_macro_node(this); } virtual int Opcode() const; virtual const Type* add_ring(const Type* t0, const Type* t1) const; @@ -376,8 +376,8 @@ class MaxLNode : public MaxNode { class MinLNode : public MaxNode { public: MinLNode(Compile* C, Node* in1, Node* in2) : MaxNode(in1, in2) { - init_flags(Flag_is_macro); - C->add_macro_node(this); + // init_flags(Flag_is_macro); + // C->add_macro_node(this); } virtual int Opcode() const; virtual const Type* add_ring(const Type* t0, const Type* t1) const; diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index c6ed2411fe3..f679b7fdaea 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2447,8 +2447,8 @@ void PhaseMacroExpand::eliminate_macro_nodes() { n->Opcode() == Op_ModF || n->is_OpaqueNotNull() || n->is_OpaqueInitializedAssertionPredicate() || - n->Opcode() == Op_MaxL || - n->Opcode() == Op_MinL || + // n->Opcode() == Op_MaxL || + // n->Opcode() == Op_MinL || BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(n), "unknown node type in macro list"); } @@ -2522,19 +2522,21 @@ bool PhaseMacroExpand::expand_macro_nodes() { } else if (n->Opcode() == Op_OuterStripMinedLoop) { C->remove_macro_node(n); success = true; - } else if (n->Opcode() == Op_MaxL) { - // Since MaxL and MinL are not implemented in the backend, we expand them to - // a CMoveL construct now. At least until here, the type could be computed - // precisely. CMoveL is not so smart, but we can give it at least the best - // type we know abouot n now. - Node* repl = MaxNode::signed_max(n->in(1), n->in(2), _igvn.type(n), _igvn); - _igvn.replace_node(n, repl); - success = true; - } else if (n->Opcode() == Op_MinL) { - Node* repl = MaxNode::signed_min(n->in(1), n->in(2), _igvn.type(n), _igvn); - _igvn.replace_node(n, repl); - success = true; } + // else if (n->Opcode() == Op_MaxL) { + // // Since MaxL and MinL are not implemented in the backend, we expand them to + // // a CMoveL construct now. At least until here, the type could be computed + // // precisely. CMoveL is not so smart, but we can give it at least the best + // // type we know abouot n now. + // Node* repl = MaxNode::signed_max(n->in(1), n->in(2), _igvn.type(n), _igvn); + // _igvn.replace_node(n, repl); + // success = true; + // } + // else if (n->Opcode() == Op_MinL) { + // Node* repl = MaxNode::signed_min(n->in(1), n->in(2), _igvn.type(n), _igvn); + // _igvn.replace_node(n, repl); + // success = true; + // } assert(!success || (C->macro_count() == (old_macro_count - 1)), "elimination must have deleted one node from macro list"); progress = progress || success; if (success) { -- 2.49.0