24
#include "precompiled.hpp"
28
#include "peephole_x86_64.hpp"
29
#include "adfiles/ad_x86.hpp"
36
static bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
37
MachNode* (*new_root)(), uint inst0_rule, bool imm) {
38
MachNode* inst0 = block->get_node(block_index)->as_Mach();
39
assert(inst0->rule() == inst0_rule, "sanity");
41
OptoReg::Name dst = ra_->get_reg_first(inst0);
42
MachNode* inst1 = nullptr;
43
OptoReg::Name src1 = OptoReg::Bad;
45
if (inst0->in(1)->is_MachSpillCopy()) {
46
OptoReg::Name in = ra_->get_reg_first(inst0->in(1)->in(1));
47
if (OptoReg::is_reg(in) && OptoReg::as_VMReg(in)->is_Register()) {
48
inst1 = inst0->in(1)->as_Mach();
52
if (inst1 == nullptr) {
55
assert(dst != src1, "");
59
if (block_index < 1 || block->get_node(block_index - 1) != inst1) {
62
int inst1_index = block_index - 1;
75
Register rsrc1 = OptoReg::as_VMReg(src1)->as_Register();
76
Register rsrc2 = OptoReg::as_VMReg(ra_->get_reg_first(inst2))->as_Register();
77
if ((rsrc1 == rbp || rsrc1 == r13) && (rsrc2 == rbp || rsrc2 == r13)) {
85
for (uint pos = block_index + 1; pos < block->number_of_nodes(); pos++) {
86
Node* curr = block->get_node(pos);
87
if (curr->is_MachProj() && curr->in(0) == inst0) {
93
assert(proj != nullptr, "");
95
if (proj->outcnt() > 0) {
99
MachNode* root = new_root();
101
ra_->set_oop(root, ra_->is_oop(inst0));
102
ra_->set_pair(root->_idx, ra_->get_reg_second(inst0), ra_->get_reg_first(inst0));
105
root->add_req(inst0->in(0));
106
root->add_req(inst1->in(1));
109
root->add_req(inst2);
111
inst0->replace_by(root);
112
proj->set_req(0, inst0);
115
root->_opnds[0] = inst0->_opnds[0]->clone();
116
root->_opnds[1] = inst0->_opnds[1]->clone();
117
root->_opnds[2] = inst0->_opnds[2]->clone();
120
inst0->set_removed();
121
inst1->set_removed();
122
block->remove_node(proj_index);
123
block->remove_node(block_index);
124
block->remove_node(inst1_index);
125
block->insert_node(root, block_index - 1);
128
cfg_->map_node_to_block(inst0, nullptr);
129
cfg_->map_node_to_block(inst1, nullptr);
130
cfg_->map_node_to_block(proj, nullptr);
131
cfg_->map_node_to_block(root, block);
139
static juint map_condition_to_required_test_flags(Assembler::Condition condition) {
141
case Assembler::Condition::zero:
142
case Assembler::Condition::notZero:
143
return Node::PD::Flag_sets_zero_flag;
144
case Assembler::Condition::less:
145
case Assembler::Condition::greaterEqual:
146
return Node::PD::Flag_sets_sign_flag | Node::PD::Flag_clears_overflow_flag;
147
case Assembler::Condition::lessEqual:
148
case Assembler::Condition::greater:
149
return Node::PD::Flag_sets_sign_flag | Node::PD::Flag_clears_overflow_flag | Node::PD::Flag_sets_zero_flag;
150
case Assembler::Condition::below:
151
case Assembler::Condition::aboveEqual:
152
return Node::PD::Flag_clears_carry_flag;
153
case Assembler::Condition::belowEqual:
154
case Assembler::Condition::above:
155
return Node::PD::Flag_clears_carry_flag | Node::PD::Flag_sets_zero_flag;
156
case Assembler::Condition::overflow:
157
case Assembler::Condition::noOverflow:
158
return Node::PD::Flag_clears_overflow_flag;
159
case Assembler::Condition::negative:
160
case Assembler::Condition::positive:
161
return Node::PD::Flag_sets_sign_flag;
162
case Assembler::Condition::parity:
163
case Assembler::Condition::noParity:
164
return Node::PD::Flag_sets_parity_flag;
166
ShouldNotReachHere();
175
bool Peephole::test_may_remove(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
176
MachNode* (*new_root)(), uint inst0_rule) {
177
MachNode* test_to_check = block->get_node(block_index)->as_Mach();
178
assert(test_to_check->rule() == inst0_rule, "sanity");
180
Node* inst1 = test_to_check->in(1);
183
if (block_index < 2 || block->get_node(block_index - 2) != inst1) {
186
if (inst1 != nullptr) {
187
MachNode* prevNode = inst1->isa_Mach();
188
if (prevNode != nullptr) {
190
juint all_node_flags = prevNode->flags();
191
if (all_node_flags == 0) {
195
juint required_flags = 0;
197
for (DUIterator_Fast imax, i = test_to_check->fast_outs(imax); i < imax; i++) {
198
MachNode* node_out = test_to_check->fast_out(i)->isa_Mach();
199
bool found_correct_oper = false;
200
for (uint16_t j = 0; j < node_out->_num_opnds; ++j) {
201
MachOper* operand = node_out->_opnds[j];
202
if (operand->opcode() == cmpOp_rule || operand->opcode() == cmpOpU_rule) {
203
auto condition = static_cast<Assembler::Condition>(operand->ccode());
204
juint flags_for_inst = map_condition_to_required_test_flags(condition);
205
required_flags = required_flags | flags_for_inst;
206
found_correct_oper = true;
210
if (!found_correct_oper) {
215
assert(required_flags != 0, "No flags required, should be impossible!");
216
bool sets_all_required_flags = (required_flags & ~all_node_flags) == 0;
217
if (sets_all_required_flags) {
219
MachProjNode* machProjNode = block->get_node(block_index - 1)->isa_MachProj();
220
assert(machProjNode != nullptr, "Expected a MachProj node here!");
221
assert(ra_->get_reg_first(machProjNode) == ra_->get_reg_first(test_to_check), "Test must operate on the same register as its replacement");
224
test_to_check->replace_by(machProjNode);
227
test_to_check->set_removed();
228
block->remove_node(block_index);
231
cfg_->map_node_to_block(test_to_check, nullptr);
239
bool Peephole::lea_coalesce_reg(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
240
MachNode* (*new_root)(), uint inst0_rule) {
241
return lea_coalesce_helper(block, block_index, cfg_, ra_, new_root, inst0_rule, false);
244
bool Peephole::lea_coalesce_imm(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
245
MachNode* (*new_root)(), uint inst0_rule) {
246
return lea_coalesce_helper(block, block_index, cfg_, ra_, new_root, inst0_rule, true);