diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp index 5fc39e163e126..f8aaa76bc0819 100644 --- a/src/hotspot/cpu/x86/peephole_x86_64.cpp +++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp @@ -338,6 +338,29 @@ bool Peephole::lea_remove_redundant(Block* block, int block_index, PhaseCFG* cfg } // We now have verified that the decode is redundant and can be removed with a peephole. + + // Before rewiring, check that the new base won't create a register conflict. + // The new base (lea_address) might share a register with a dependant_lea. + // If the dependant_lea overwrites that register and the base is still live + // (used in successor blocks), this creates a conflict detected by verify_good_schedule. + Node* new_base = lea_derived_oop->in(AddPNode::Address); + OptoReg::Name new_base_reg = ra_->get_reg_first(new_base); + if (OptoReg::is_valid(new_base_reg)) { + for (DUIterator_Fast imax, i = decode->fast_outs(imax); i < imax; i++) { + Node* dependant_lea = decode->fast_out(i); + if (dependant_lea->is_Mach() && dependant_lea->as_Mach()->ideal_Opcode() == Op_AddP) { + OptoReg::Name lea_reg = ra_->get_reg_first(dependant_lea); + OptoReg::Name lea_reg2 = ra_->get_reg_second(dependant_lea); + // If the new base register overlaps with any register slot of + // the dependant lea's output, the rewiring would create a conflict + // when the lea overwrites the base pointer's register. + if (new_base_reg == lea_reg || new_base_reg == lea_reg2) { + return false; + } + } + } + } + // Remove the projection block->find_remove(proj); cfg_->map_node_to_block(proj, nullptr); @@ -346,7 +369,7 @@ bool Peephole::lea_remove_redundant(Block* block, int block_index, PhaseCFG* cfg for (DUIterator_Fast imax, i = decode->fast_outs(imax); i < imax; i++) { Node* dependant_lea = decode->fast_out(i); if (dependant_lea->is_Mach() && dependant_lea->as_Mach()->ideal_Opcode() == Op_AddP) { - dependant_lea->set_req(AddPNode::Base, lea_derived_oop->in(AddPNode::Address)); + dependant_lea->set_req(AddPNode::Base, new_base); // This deleted something in the out array, hence adjust i, imax. --i; --imax; diff --git a/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java index 0108df4070411..9458903dfbcec 100644 --- a/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java +++ b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java @@ -298,8 +298,11 @@ class StoreNTest { @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "false"}) - // Test that the peephole worked for leaPCompressedOopOffset - @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + // Test that the peephole worked for leaPCompressedOopOffset. + // The peephole may bail out if the new base pointer's register + // would conflict with a dependent lea's output register, so we + // allow up to the non-peephole count. + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "<=2"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "true"}) // Test that the peephole removes a spill. @@ -340,8 +343,9 @@ public void testPhiSpill() { @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "false"}) - // Test that the peephole worked for leaPCompressedOopOffset - @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + // Test that the peephole worked for leaPCompressedOopOffset. + // The peephole may bail out due to register conflicts. + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "<=2"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "true"}) public void testNoAlloc() { @@ -357,8 +361,9 @@ public void testNoAlloc() { @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "false"}) - // Test that the peephole worked for leaPCompressedOopOffset - @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + // Test that the peephole worked for leaPCompressedOopOffset. + // The peephole may bail out due to register conflicts. + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "<=1"}, phase = {CompilePhase.FINAL_CODE}, applyIf = {"OptoPeephole", "true"}) public void testNoAllocSameArray() {