8312213: Remove unnecessary TEST instructions on x86 when flags reg will already be set
Reviewed-by: jvernee, dlong
This commit is contained in:
parent
1f4cdb327f
commit
aba89f20bf
src/hotspot
cpu/x86
share/adlc
test
hotspot/jtreg/compiler
micro/org/openjdk/bench/vm/compiler/x86
@ -26,6 +26,7 @@
|
||||
#ifdef COMPILER2
|
||||
|
||||
#include "peephole_x86_64.hpp"
|
||||
#include "adfiles/ad_x86.hpp"
|
||||
|
||||
// This function transforms the shapes
|
||||
// mov d, s1; add d, s2 into
|
||||
@ -132,6 +133,109 @@ bool lea_coalesce_helper(Block* block, int block_index, PhaseCFG* cfg_, PhaseReg
|
||||
return true;
|
||||
}
|
||||
|
||||
// This helper func takes a condition and returns the flags that need to be set for the condition
|
||||
// It uses the same flags as the test instruction, so if the e.g. the overflow bit is required,
|
||||
// this func returns clears_overflow, as that is what the test instruction does and what the downstream path expects
|
||||
juint map_condition_to_required_test_flags(Assembler::Condition condition) {
|
||||
switch (condition) {
|
||||
case Assembler::Condition::zero: // Same value as equal
|
||||
case Assembler::Condition::notZero: // Same value as notEqual
|
||||
return Node::PD::Flag_sets_zero_flag;
|
||||
case Assembler::Condition::less:
|
||||
case Assembler::Condition::greaterEqual:
|
||||
return Node::PD::Flag_sets_sign_flag | Node::PD::Flag_clears_overflow_flag;
|
||||
case Assembler::Condition::lessEqual:
|
||||
case Assembler::Condition::greater:
|
||||
return Node::PD::Flag_sets_sign_flag | Node::PD::Flag_clears_overflow_flag | Node::PD::Flag_sets_zero_flag;
|
||||
case Assembler::Condition::below: // Same value as carrySet
|
||||
case Assembler::Condition::aboveEqual: // Same value as carryClear
|
||||
return Node::PD::Flag_clears_carry_flag;
|
||||
case Assembler::Condition::belowEqual:
|
||||
case Assembler::Condition::above:
|
||||
return Node::PD::Flag_clears_carry_flag | Node::PD::Flag_sets_zero_flag;
|
||||
case Assembler::Condition::overflow:
|
||||
case Assembler::Condition::noOverflow:
|
||||
return Node::PD::Flag_clears_overflow_flag;
|
||||
case Assembler::Condition::negative:
|
||||
case Assembler::Condition::positive:
|
||||
return Node::PD::Flag_sets_sign_flag;
|
||||
case Assembler::Condition::parity:
|
||||
case Assembler::Condition::noParity:
|
||||
return Node::PD::Flag_sets_parity_flag;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function removes the TEST instruction when it detected shapes likes AND r1, r2; TEST r1, r1
|
||||
// It checks the required EFLAGS for the downstream instructions of the TEST
|
||||
// and removes the TEST if the preceding instructions already sets all these flags
|
||||
bool Peephole::test_may_remove(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
|
||||
MachNode* (*new_root)(), uint inst0_rule) {
|
||||
MachNode* test_to_check = block->get_node(block_index)->as_Mach();
|
||||
assert(test_to_check->rule() == inst0_rule, "sanity");
|
||||
|
||||
Node* inst1 = test_to_check->in(1);
|
||||
// Only remove test if the block order is inst1 -> MachProjNode (because the node to match must specify KILL cr) -> test_to_check
|
||||
// So inst1 must be at index - 2
|
||||
if (block_index < 2 || block->get_node(block_index - 2) != inst1) {
|
||||
return false;
|
||||
}
|
||||
if (inst1 != nullptr) {
|
||||
MachNode* prevNode = inst1->isa_Mach();
|
||||
if (prevNode != nullptr) {
|
||||
// Includes other flags as well, but that doesn't matter here
|
||||
juint all_node_flags = prevNode->flags();
|
||||
if (all_node_flags == 0) {
|
||||
// We can return early - there is no way the test can be removed, the preceding node does not set any flags
|
||||
return false;
|
||||
}
|
||||
juint required_flags = 0;
|
||||
// Search for the uses of the node and compute which flags are required
|
||||
for (DUIterator_Fast imax, i = test_to_check->fast_outs(imax); i < imax; i++) {
|
||||
MachNode* node_out = test_to_check->fast_out(i)->isa_Mach();
|
||||
bool found_correct_oper = false;
|
||||
for (uint16_t j = 0; j < node_out->_num_opnds; ++j) {
|
||||
MachOper* operand = node_out->_opnds[j];
|
||||
if (operand->opcode() == cmpOp_rule || operand->opcode() == cmpOpU_rule) {
|
||||
auto condition = static_cast<Assembler::Condition>(operand->ccode());
|
||||
juint flags_for_inst = map_condition_to_required_test_flags(condition);
|
||||
required_flags = required_flags | flags_for_inst;
|
||||
found_correct_oper = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_correct_oper) {
|
||||
// We could not find one the required flags for one of the dependencies. Keep the test as it might set flags needed for that node
|
||||
return false;
|
||||
}
|
||||
}
|
||||
assert(required_flags != 0, "No flags required, should be impossible!");
|
||||
bool sets_all_required_flags = (required_flags & ~all_node_flags) == 0;
|
||||
if (sets_all_required_flags) {
|
||||
// All flags are covered are clear to remove this test
|
||||
MachProjNode* machProjNode = block->get_node(block_index - 1)->isa_MachProj();
|
||||
assert(machProjNode != nullptr, "Expected a MachProj node here!");
|
||||
assert(ra_->get_reg_first(machProjNode) == ra_->get_reg_first(test_to_check), "Test must operate on the same register as its replacement");
|
||||
|
||||
// Remove the original test node and replace it with the pseudo test node. The AND node already sets ZF
|
||||
test_to_check->replace_by(machProjNode);
|
||||
|
||||
// Modify the block
|
||||
test_to_check->set_removed();
|
||||
block->remove_node(block_index);
|
||||
|
||||
// Modify the control flow
|
||||
cfg_->map_node_to_block(test_to_check, nullptr);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Peephole::lea_coalesce_reg(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
|
||||
MachNode* (*new_root)(), uint inst0_rule) {
|
||||
return lea_coalesce_helper(block, block_index, cfg_, ra_, new_root, inst0_rule, false);
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
MachNode* (*new_root)(), uint inst0_rule);
|
||||
static bool lea_coalesce_imm(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
|
||||
MachNode* (*new_root)(), uint inst0_rule);
|
||||
static bool test_may_remove(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_,
|
||||
MachNode* (*new_root)(), uint inst0_rule);
|
||||
};
|
||||
|
||||
#endif // CPU_X86_PEEPHOLE_X86_64_HPP
|
||||
|
@ -1254,8 +1254,18 @@ static inline bool is_clz_non_subword_predicate_evex(BasicType bt, int vlen_byte
|
||||
class Node::PD {
|
||||
public:
|
||||
enum NodeFlags {
|
||||
Flag_intel_jcc_erratum = Node::_last_flag << 1,
|
||||
_last_flag = Flag_intel_jcc_erratum
|
||||
Flag_intel_jcc_erratum = Node::_last_flag << 1,
|
||||
Flag_sets_carry_flag = Node::_last_flag << 2,
|
||||
Flag_sets_parity_flag = Node::_last_flag << 3,
|
||||
Flag_sets_zero_flag = Node::_last_flag << 4,
|
||||
Flag_sets_overflow_flag = Node::_last_flag << 5,
|
||||
Flag_sets_sign_flag = Node::_last_flag << 6,
|
||||
Flag_clears_carry_flag = Node::_last_flag << 7,
|
||||
Flag_clears_parity_flag = Node::_last_flag << 8,
|
||||
Flag_clears_zero_flag = Node::_last_flag << 9,
|
||||
Flag_clears_overflow_flag = Node::_last_flag << 10,
|
||||
Flag_clears_sign_flag = Node::_last_flag << 11,
|
||||
_last_flag = Flag_clears_sign_flag
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -7649,7 +7649,7 @@ instruct addI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI dst src));
|
||||
effect(KILL cr);
|
||||
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
format %{ "addl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
__ addl($dst$$Register, $src$$Register);
|
||||
@ -7661,6 +7661,7 @@ instruct addI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "addl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -7673,6 +7674,7 @@ instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddI dst (LoadI src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150); // XXX
|
||||
format %{ "addl $dst, $src\t# int" %}
|
||||
@ -7686,6 +7688,7 @@ instruct addI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (AddI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150); // XXX
|
||||
format %{ "addl $dst, $src\t# int" %}
|
||||
@ -7699,6 +7702,8 @@ instruct addI_mem_imm(memory dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (AddI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
|
||||
ins_cost(125); // XXX
|
||||
format %{ "addl $dst, $src\t# int" %}
|
||||
@ -7819,6 +7824,7 @@ instruct addL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "addq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -7831,6 +7837,7 @@ instruct addL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "addq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -7843,6 +7850,7 @@ instruct addL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddL dst (LoadL src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150); // XXX
|
||||
format %{ "addq $dst, $src\t# long" %}
|
||||
@ -7856,6 +7864,7 @@ instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (AddL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150); // XXX
|
||||
format %{ "addq $dst, $src\t# long" %}
|
||||
@ -7869,6 +7878,7 @@ instruct addL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (AddL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(125); // XXX
|
||||
format %{ "addq $dst, $src\t# long" %}
|
||||
@ -7989,6 +7999,7 @@ instruct addP_rReg(rRegP dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddP dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "addq $dst, $src\t# ptr" %}
|
||||
ins_encode %{
|
||||
@ -8001,6 +8012,7 @@ instruct addP_rReg_imm(rRegP dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AddP dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "addq $dst, $src\t# ptr" %}
|
||||
ins_encode %{
|
||||
@ -8554,6 +8566,7 @@ instruct subI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "subl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -8566,6 +8579,7 @@ instruct subI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI dst (LoadI src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "subl $dst, $src\t# int" %}
|
||||
@ -8579,6 +8593,7 @@ instruct subI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (SubI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "subl $dst, $src\t# int" %}
|
||||
@ -8592,6 +8607,7 @@ instruct subL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "subq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -8604,6 +8620,7 @@ instruct subL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL dst (LoadL src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "subq $dst, $src\t# long" %}
|
||||
@ -8617,6 +8634,7 @@ instruct subL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (SubL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "subq $dst, $src\t# long" %}
|
||||
@ -8643,6 +8661,7 @@ instruct negI_rReg(rRegI dst, immI_0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubI zero dst));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negl $dst\t# int" %}
|
||||
ins_encode %{
|
||||
@ -8655,6 +8674,7 @@ instruct negI_rReg_2(rRegI dst, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (NegI dst));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negl $dst\t# int" %}
|
||||
ins_encode %{
|
||||
@ -8667,6 +8687,7 @@ instruct negI_mem(memory dst, immI_0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (SubI zero (LoadI dst))));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negl $dst\t# int" %}
|
||||
ins_encode %{
|
||||
@ -8679,6 +8700,7 @@ instruct negL_rReg(rRegL dst, immL0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (SubL zero dst));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negq $dst\t# long" %}
|
||||
ins_encode %{
|
||||
@ -8691,6 +8713,7 @@ instruct negL_rReg_2(rRegL dst, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (NegL dst));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negq $dst\t# int" %}
|
||||
ins_encode %{
|
||||
@ -8703,6 +8726,7 @@ instruct negL_mem(memory dst, immL0 zero, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (SubL zero (LoadL dst))));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
format %{ "negq $dst\t# long" %}
|
||||
ins_encode %{
|
||||
@ -9184,6 +9208,7 @@ instruct sarI_rReg_CL(rRegI dst, rcx_RegI shift, rFlagsReg cr)
|
||||
predicate(!VM_Version::supports_bmi2());
|
||||
match(Set dst (RShiftI dst shift));
|
||||
effect(KILL cr);
|
||||
|
||||
format %{ "sarl $dst, $shift" %}
|
||||
ins_encode %{
|
||||
__ sarl($dst$$Register);
|
||||
@ -9838,6 +9863,7 @@ instruct andI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -9914,6 +9940,7 @@ instruct andI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -9927,6 +9954,7 @@ instruct andI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndI dst (LoadI src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "andl $dst, $src\t# int" %}
|
||||
@ -9941,6 +9969,7 @@ instruct andB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreB dst (AndI (LoadB dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "andb $dst, $src\t# byte" %}
|
||||
@ -9954,6 +9983,7 @@ instruct andI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (AndI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "andl $dst, $src\t# int" %}
|
||||
@ -9968,6 +9998,7 @@ instruct andI_mem_imm(memory dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (AndI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "andl $dst, $src\t# int" %}
|
||||
@ -9982,6 +10013,7 @@ instruct andnI_rReg_rReg_mem(rRegI dst, rRegI src1, memory src2, immI_M1 minus_1
|
||||
match(Set dst (AndI (XorI src1 minus_1) (LoadI src2)));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "andnl $dst, $src1, $src2" %}
|
||||
@ -9996,6 +10028,7 @@ instruct andnI_rReg_rReg_rReg(rRegI dst, rRegI src1, rRegI src2, immI_M1 minus_1
|
||||
match(Set dst (AndI (XorI src1 minus_1) src2));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andnl $dst, $src1, $src2" %}
|
||||
|
||||
@ -10009,6 +10042,7 @@ instruct blsiI_rReg_rReg(rRegI dst, rRegI src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (SubI imm_zero src) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsil $dst, $src" %}
|
||||
|
||||
@ -10022,6 +10056,7 @@ instruct blsiI_rReg_mem(rRegI dst, memory src, immI_0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndI (SubI imm_zero (LoadI src) ) (LoadI src) ));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsil $dst, $src" %}
|
||||
@ -10037,6 +10072,7 @@ instruct blsmskI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (XorI (AddI (LoadI src) minus_1) (LoadI src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsmskl $dst, $src" %}
|
||||
@ -10052,6 +10088,7 @@ instruct blsmskI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (XorI (AddI src minus_1) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsmskl $dst, $src" %}
|
||||
|
||||
@ -10067,6 +10104,7 @@ instruct blsrI_rReg_rReg(rRegI dst, rRegI src, immI_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (AndI (AddI src minus_1) src) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsrl $dst, $src" %}
|
||||
|
||||
@ -10082,6 +10120,7 @@ instruct blsrI_rReg_mem(rRegI dst, memory src, immI_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (AndI (AddI (LoadI src) minus_1) (LoadI src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsrl $dst, $src" %}
|
||||
@ -10099,6 +10138,7 @@ instruct orI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "orl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -10112,6 +10152,7 @@ instruct orI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "orl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -10125,6 +10166,7 @@ instruct orI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrI dst (LoadI src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "orl $dst, $src\t# int" %}
|
||||
@ -10139,6 +10181,7 @@ instruct orB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreB dst (OrI (LoadB dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "orb $dst, $src\t# byte" %}
|
||||
@ -10152,6 +10195,7 @@ instruct orI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (OrI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "orl $dst, $src\t# int" %}
|
||||
@ -10166,6 +10210,7 @@ instruct orI_mem_imm(memory dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (OrI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "orl $dst, $src\t# int" %}
|
||||
@ -10181,6 +10226,7 @@ instruct xorI_rReg(rRegI dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "xorl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -10205,6 +10251,7 @@ instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorI dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "xorl $dst, $src\t# int" %}
|
||||
ins_encode %{
|
||||
@ -10218,6 +10265,7 @@ instruct xorI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorI dst (LoadI src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "xorl $dst, $src\t# int" %}
|
||||
@ -10232,6 +10280,7 @@ instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreB dst (XorI (LoadB dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "xorb $dst, $src\t# byte" %}
|
||||
@ -10245,6 +10294,7 @@ instruct xorI_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (XorI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "xorl $dst, $src\t# int" %}
|
||||
@ -10259,6 +10309,7 @@ instruct xorI_mem_imm(memory dst, immI src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreI dst (XorI (LoadI dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "xorl $dst, $src\t# int" %}
|
||||
@ -10277,6 +10328,7 @@ instruct andL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10316,6 +10368,7 @@ instruct andL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10329,6 +10382,7 @@ instruct andL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (AndL dst (LoadL src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "andq $dst, $src\t# long" %}
|
||||
@ -10343,6 +10397,7 @@ instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (AndL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "andq $dst, $src\t# long" %}
|
||||
@ -10357,6 +10412,7 @@ instruct andL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (AndL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "andq $dst, $src\t# long" %}
|
||||
@ -10388,6 +10444,7 @@ instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1
|
||||
match(Set dst (AndL (XorL src1 minus_1) (LoadL src2)));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "andnq $dst, $src1, $src2" %}
|
||||
@ -10402,6 +10459,7 @@ instruct andnL_rReg_rReg_rReg(rRegL dst, rRegL src1, rRegL src2, immL_M1 minus_1
|
||||
match(Set dst (AndL (XorL src1 minus_1) src2));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "andnq $dst, $src1, $src2" %}
|
||||
|
||||
@ -10415,6 +10473,7 @@ instruct blsiL_rReg_rReg(rRegL dst, rRegL src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (SubL imm_zero src) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsiq $dst, $src" %}
|
||||
|
||||
@ -10428,6 +10487,7 @@ instruct blsiL_rReg_mem(rRegL dst, memory src, immL0 imm_zero, rFlagsReg cr) %{
|
||||
match(Set dst (AndL (SubL imm_zero (LoadL src) ) (LoadL src) ));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsiq $dst, $src" %}
|
||||
@ -10443,6 +10503,7 @@ instruct blsmskL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (XorL (AddL (LoadL src) minus_1) (LoadL src) ) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsmskq $dst, $src" %}
|
||||
@ -10458,6 +10519,7 @@ instruct blsmskL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (XorL (AddL src minus_1) src));
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_clears_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsmskq $dst, $src" %}
|
||||
|
||||
@ -10473,6 +10535,7 @@ instruct blsrL_rReg_rReg(rRegL dst, rRegL src, immL_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (AndL (AddL src minus_1) src) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
format %{ "blsrq $dst, $src" %}
|
||||
|
||||
@ -10488,6 +10551,7 @@ instruct blsrL_rReg_mem(rRegL dst, memory src, immL_M1 minus_1, rFlagsReg cr)
|
||||
match(Set dst (AndL (AddL (LoadL src) minus_1) (LoadL src)) );
|
||||
predicate(UseBMI1Instructions);
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_clears_overflow_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "blsrq $dst, $src" %}
|
||||
@ -10505,6 +10569,7 @@ instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10517,6 +10582,7 @@ instruct orL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
instruct orL_rReg_castP2X(rRegL dst, any_RegP src, rFlagsReg cr) %{
|
||||
match(Set dst (OrL dst (CastP2X src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10531,6 +10597,7 @@ instruct orL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10544,6 +10611,7 @@ instruct orL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (OrL dst (LoadL src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
@ -10558,6 +10626,7 @@ instruct orL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (OrL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
@ -10572,6 +10641,7 @@ instruct orL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (OrL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "orq $dst, $src\t# long" %}
|
||||
@ -10604,6 +10674,7 @@ instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "xorq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10628,6 +10699,7 @@ instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorL dst src));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
format %{ "xorq $dst, $src\t# long" %}
|
||||
ins_encode %{
|
||||
@ -10641,6 +10713,7 @@ instruct xorL_rReg_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (XorL dst (LoadL src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "xorq $dst, $src\t# long" %}
|
||||
@ -10655,6 +10728,7 @@ instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (XorL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "xorq $dst, $src\t# long" %}
|
||||
@ -10669,6 +10743,7 @@ instruct xorL_mem_imm(memory dst, immL32 src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (XorL (LoadL dst) src)));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(125);
|
||||
format %{ "xorq $dst, $src\t# long" %}
|
||||
@ -13863,6 +13938,24 @@ peephole
|
||||
peepreplace (leaL_rReg_immI2_peep());
|
||||
%}
|
||||
|
||||
// These peephole rules matches instructions which set flags and are followed by a testI/L_reg
|
||||
// The test instruction is redudanent in case the downstream instuctions (like JCC or CMOV) only use flags that are already set by the previous instruction
|
||||
|
||||
//int variant
|
||||
peephole
|
||||
%{
|
||||
peepmatch (testI_reg);
|
||||
peepprocedure (test_may_remove);
|
||||
%}
|
||||
|
||||
//long variant
|
||||
peephole
|
||||
%{
|
||||
peepmatch (testL_reg);
|
||||
peepprocedure (test_may_remove);
|
||||
%}
|
||||
|
||||
|
||||
//----------SMARTSPILL RULES---------------------------------------------------
|
||||
// These must follow all instruction definitions as they use the names
|
||||
// defined in the instructions definitions.
|
||||
|
@ -229,6 +229,7 @@ void ADLParser::instr_parse(void) {
|
||||
else if (!strcmp(ident, "opcode")) instr->_opcode = opcode_parse(instr);
|
||||
else if (!strcmp(ident, "size")) instr->_size = size_parse(instr);
|
||||
else if (!strcmp(ident, "effect")) effect_parse(instr);
|
||||
else if (!strcmp(ident, "flag")) instr->_flag = flag_parse(instr);
|
||||
else if (!strcmp(ident, "expand")) instr->_exprule = expand_parse(instr);
|
||||
else if (!strcmp(ident, "rewrite")) instr->_rewrule = rewrite_parse();
|
||||
else if (!strcmp(ident, "constraint")) {
|
||||
@ -4126,6 +4127,46 @@ void ADLParser::effect_parse(InstructForm *instr) {
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------flag_parse------------------------------------
|
||||
Flag* ADLParser::flag_parse(InstructForm *instr) {
|
||||
char* ident = nullptr;
|
||||
Flag* result = nullptr;
|
||||
|
||||
skipws(); // Skip whitespace
|
||||
if (_curchar != '(') {
|
||||
parse_err(SYNERR, "missing '(' in flag definition\n");
|
||||
return nullptr;
|
||||
}
|
||||
do {
|
||||
next_char();
|
||||
skipws();
|
||||
if (_curchar == ')') break;
|
||||
|
||||
ident = get_ident();
|
||||
if (ident == nullptr) {
|
||||
parse_err(SYNERR, "flag name expected at %c\n", _curchar);
|
||||
return nullptr;
|
||||
}
|
||||
Flag* newflag = new Flag(ident);
|
||||
if (result == nullptr) result = newflag;
|
||||
else result->append_flag(newflag);
|
||||
if (_AD._adl_debug > 1) fprintf(stderr, "\tFlag Name: %s\n", ident);
|
||||
skipws();
|
||||
} while (_curchar == ',');
|
||||
if (_curchar != ')') parse_err(SYNERR, "missing ')'\n");
|
||||
else {
|
||||
next_char(); // set current character position past the close paren
|
||||
}
|
||||
|
||||
// Debug Stuff
|
||||
if (_curchar != ';') {
|
||||
parse_err(SYNERR, "missing ';' in Flag definition\n");
|
||||
}
|
||||
// Skip ';'
|
||||
next_char();
|
||||
return result;
|
||||
}
|
||||
|
||||
//------------------------------expand_parse-----------------------------------
|
||||
ExpandRule* ADLParser::expand_parse(InstructForm *instr) {
|
||||
char *ident, *ident2;
|
||||
|
@ -47,6 +47,7 @@ class Encode;
|
||||
class Attribute;
|
||||
class Effect;
|
||||
class ExpandRule;
|
||||
class Flag;
|
||||
class RewriteRule;
|
||||
class Constraint;
|
||||
class ConstructRule;
|
||||
@ -177,6 +178,7 @@ protected:
|
||||
FormatRule *format_parse(void); // Parse format rule
|
||||
FormatRule *template_parse(void); // Parse format rule
|
||||
void effect_parse(InstructForm *instr); // Parse effect rule
|
||||
Flag *flag_parse(InstructForm *instr); // Parse flag rule
|
||||
ExpandRule *expand_parse(InstructForm *instr); // Parse expand rule
|
||||
RewriteRule *rewrite_parse(void); // Parse rewrite rule
|
||||
Constraint *constraint_parse(void); // Parse constraint rule
|
||||
|
@ -54,6 +54,7 @@ class MatchRule;
|
||||
class Attribute;
|
||||
class Effect;
|
||||
class ExpandRule;
|
||||
class Flag;
|
||||
class RewriteRule;
|
||||
class ConstructRule;
|
||||
class FormatRule;
|
||||
@ -237,6 +238,7 @@ public:
|
||||
EXP,
|
||||
REW,
|
||||
EFF,
|
||||
FLG,
|
||||
RDEF,
|
||||
RCL,
|
||||
ACL,
|
||||
|
@ -44,6 +44,7 @@ class MatchRule;
|
||||
class Attribute;
|
||||
class Effect;
|
||||
class ExpandRule;
|
||||
class Flag;
|
||||
class RewriteRule;
|
||||
class ConstructRule;
|
||||
class FormatRule;
|
||||
|
@ -52,6 +52,7 @@ InstructForm::InstructForm(const char *id, bool ideal_only)
|
||||
_format = nullptr;
|
||||
_peephole = nullptr;
|
||||
_ins_pipe = nullptr;
|
||||
_flag = nullptr;
|
||||
_uniq_idx = nullptr;
|
||||
_num_uniq = 0;
|
||||
_cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill
|
||||
@ -86,6 +87,7 @@ InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)
|
||||
_format = instr->_format;
|
||||
_peephole = instr->_peephole;
|
||||
_ins_pipe = instr->_ins_pipe;
|
||||
_flag = instr->_flag;
|
||||
_uniq_idx = instr->_uniq_idx;
|
||||
_num_uniq = instr->_num_uniq;
|
||||
_cisc_spill_operand = Not_cisc_spillable; // Which operand may cisc-spill
|
||||
@ -1893,6 +1895,34 @@ void Effect::output(FILE *fp) { // Write info to output files
|
||||
fprintf(fp,"Effect: %s\n", (_name?_name:""));
|
||||
}
|
||||
|
||||
//---------------------------------Flag----------------------------------------
|
||||
Flag::Flag(const char *name) : _name(name), _next(nullptr) {
|
||||
_ftype = Form::FLG;
|
||||
}
|
||||
|
||||
Flag::~Flag() {
|
||||
}
|
||||
|
||||
void Flag::append_flag(Flag *next_flag) {
|
||||
if( _next == nullptr ) {
|
||||
_next = next_flag;
|
||||
} else {
|
||||
_next->append_flag( next_flag );
|
||||
}
|
||||
}
|
||||
|
||||
Flag* Flag::next() {
|
||||
return _next;
|
||||
}
|
||||
|
||||
void Flag::dump() {
|
||||
output(stderr);
|
||||
}
|
||||
|
||||
void Flag::output(FILE *fp) { // Write info to output files
|
||||
fprintf(fp,"Flag: %s\n", (_name?_name:""));
|
||||
}
|
||||
|
||||
//------------------------------ExpandRule-------------------------------------
|
||||
ExpandRule::ExpandRule() : _expand_instrs(),
|
||||
_newopconst(cmpstr, hashstr, Form::arena) {
|
||||
|
@ -45,6 +45,7 @@ class MatchRule;
|
||||
class Attribute;
|
||||
class Effect;
|
||||
class ExpandRule;
|
||||
class Flag;
|
||||
class RewriteRule;
|
||||
class ConstructRule;
|
||||
class FormatRule;
|
||||
@ -108,6 +109,7 @@ public:
|
||||
FormatRule *_format; // Format for assembly generation
|
||||
Peephole *_peephole; // List of peephole rules for instruction
|
||||
const char *_ins_pipe; // Instruction Scheduling description class
|
||||
Flag *_flag; // List of Flags that should be set by default for this node
|
||||
|
||||
uint *_uniq_idx; // Indexes of unique operands
|
||||
uint _uniq_idx_length; // Length of _uniq_idx array
|
||||
@ -515,6 +517,26 @@ public:
|
||||
void output(FILE *fp); // Write info to output files
|
||||
};
|
||||
|
||||
//---------------------------------Flag----------------------------------------
|
||||
class Flag : public Form {
|
||||
private:
|
||||
Flag* _next;
|
||||
public:
|
||||
const char *_name; // Name of the flag (See Node::<flag_name> or Node::Pd::<flag_name>
|
||||
|
||||
// Public Methods
|
||||
Flag(const char *name); // Constructor
|
||||
~Flag(); // Destructor
|
||||
|
||||
// Append a flag rule for the same instruction
|
||||
void append_flag(Flag *next_flag);
|
||||
|
||||
Flag* next();
|
||||
|
||||
void dump(); // Debug printer
|
||||
void output(FILE *fp); // Write info to output files
|
||||
};
|
||||
|
||||
//------------------------------RewriteRule------------------------------------
|
||||
class RewriteRule : public Form {
|
||||
private:
|
||||
|
@ -1469,10 +1469,14 @@ void ArchDesc::definePeephole(FILE *fp, InstructForm *node) {
|
||||
// End of scope for this peephole's constraints
|
||||
fprintf(fp, " }\n");
|
||||
} else {
|
||||
const char* replace_inst = nullptr;
|
||||
preplace->next_instruction(replace_inst);
|
||||
// Generate the target instruction
|
||||
fprintf(fp, " auto replacing = [](){ return static_cast<MachNode*>(new %sNode()); };\n", replace_inst);
|
||||
if (preplace != nullptr) {
|
||||
const char *replace_inst = nullptr;
|
||||
preplace->next_instruction(replace_inst);
|
||||
// Generate the target instruction
|
||||
fprintf(fp, " auto replacing = [](){ return static_cast<MachNode*>(new %sNode()); };\n", replace_inst);
|
||||
} else {
|
||||
fprintf(fp, " auto replacing = nullptr;\n");
|
||||
}
|
||||
|
||||
// Call the precedure
|
||||
fprintf(fp, " bool replacement = Peephole::%s(block, block_index, cfg_, ra_, replacing", pprocedure->name());
|
||||
@ -4010,6 +4014,22 @@ void ArchDesc::buildMachNode(FILE *fp_cpp, InstructForm *inst, const char *inden
|
||||
fprintf(fp_cpp, " );\n");
|
||||
// #####
|
||||
}
|
||||
if (inst->_flag != nullptr) {
|
||||
Flag* node = inst->_flag;
|
||||
const char* prefix = "Node::";
|
||||
bool node_flags_set = false;
|
||||
do {
|
||||
if (!node_flags_set) {
|
||||
fprintf(fp_cpp, "%s node->add_flag(%s%s", indent, prefix, node->_name);
|
||||
node_flags_set = true;
|
||||
} else {
|
||||
fprintf(fp_cpp, " | %s%s", prefix, node->_name);
|
||||
}
|
||||
} while ((node = node->next()) != nullptr);
|
||||
if (node_flags_set) {
|
||||
fprintf(fp_cpp, ");\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the bottom_type where requested
|
||||
if (inst->captures_bottom_type(_globalNames)) {
|
||||
|
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package compiler.c2.irTests;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
import compiler.lib.ir_framework.*;
|
||||
import java.util.Random;
|
||||
import jdk.test.lib.Utils;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test that unnessercary test instructions are not present in the final code
|
||||
* @bug 8312213
|
||||
* @library /test/lib /
|
||||
* @requires vm.compiler2.enabled
|
||||
* @requires os.arch == "x86_64" | os.arch == "amd64"
|
||||
* @run driver compiler.c2.irTests.TestTestRemovalPeephole
|
||||
*/
|
||||
public class TestTestRemovalPeephole {
|
||||
static volatile boolean field;
|
||||
public static void main(String[] args) {
|
||||
TestFramework.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testIntAddtionEquals0(int x, int y) {
|
||||
int result = x + y;
|
||||
if (result == 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testIntAddtionNotEquals0(int x, int y) {
|
||||
int result = x + y;
|
||||
if (result != 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testLongAddtionEquals0(long x, long y) {
|
||||
long result = x + y;
|
||||
if (result == 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testLongAddtionNotEquals0(long x, long y) {
|
||||
long result = x + y;
|
||||
if (result != 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testIntOrEquals0(int x, int y) {
|
||||
int result = x | y;
|
||||
if (result == 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testIntOrNotEquals0(int x, int y) {
|
||||
int result = x | y;
|
||||
if (result != 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testLongOrEquals0(long x, long y) {
|
||||
long result = x | y;
|
||||
if (result == 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testLongOrNotEquals0(long x, long y) {
|
||||
long result = x | y;
|
||||
if (result != 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testIntOrGreater0(int x, int y) {
|
||||
int result = x | y;
|
||||
if (result > 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Arguments({Argument.RANDOM_EACH, Argument.RANDOM_EACH})
|
||||
@IR(failOn = {IRNode.X86_TESTI_REG, IRNode.X86_TESTL_REG}, phase = CompilePhase.FINAL_CODE)
|
||||
public boolean testLongOrGreater0(long x, long y) {
|
||||
long result = x | y;
|
||||
if (result > 0) {
|
||||
field = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public void assertResult(int x, int y) {
|
||||
Asserts.assertEQ((x + y) == 0, testIntAddtionEquals0(x, y));
|
||||
Asserts.assertEQ((x + y) != 0, testIntAddtionNotEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) == 0, testIntOrEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) != 0, testIntOrNotEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) > 0, testIntOrGreater0(x, y));
|
||||
}
|
||||
|
||||
@DontCompile
|
||||
public void assertResult(long x, long y) {
|
||||
Asserts.assertEQ((x + y) == 0, testLongAddtionEquals0(x, y));
|
||||
Asserts.assertEQ((x + y) != 0, testLongAddtionNotEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) == 0, testLongOrEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) != 0, testLongOrNotEquals0(x, y));
|
||||
Asserts.assertEQ((x | y) > 0, testLongOrGreater0(x, y));
|
||||
}
|
||||
}
|
@ -2119,6 +2119,16 @@ public class IRNode {
|
||||
machOnlyNameRegex(X86_LOCK_XADDL, "xaddL");
|
||||
}
|
||||
|
||||
public static final String X86_TESTI_REG = PREFIX + "X86_TESTI_REG" + POSTFIX;
|
||||
static {
|
||||
machOnlyNameRegex(X86_TESTI_REG, "testI_reg");
|
||||
}
|
||||
|
||||
public static final String X86_TESTL_REG = PREFIX + "X86_TESTL_REG" + POSTFIX;
|
||||
static {
|
||||
machOnlyNameRegex(X86_TESTL_REG, "testL_reg");
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility methods to set up IR_NODE_MAPPINGS.
|
||||
*/
|
||||
|
@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Copyright (c) 2023, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package org.openjdk.bench.vm.compiler.x86;
|
||||
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
import org.openjdk.jmh.infra.Blackhole;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||
@Fork(value = 2)
|
||||
@Warmup(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
|
||||
@Measurement(iterations = 4, time = 2, timeUnit = TimeUnit.SECONDS)
|
||||
@State(Scope.Thread)
|
||||
public class TestRemovalPeephole {
|
||||
long[] valuesLong1;
|
||||
long[] valuesLong2;
|
||||
int[] valuesInt1;
|
||||
int[] valuesInt2;
|
||||
long valueLong1;
|
||||
long valueLong2;
|
||||
int valueInt1;
|
||||
int valueInt2;
|
||||
|
||||
@Setup
|
||||
public void setup() {
|
||||
Random random = new Random(42);
|
||||
valuesLong1 = new long[128];
|
||||
valuesLong2 = new long[128];
|
||||
for (int i = 0; i < valuesLong1.length; i++) {
|
||||
valuesLong1[i] = random.nextLong();
|
||||
}
|
||||
for (int i = 0; i < valuesLong2.length; i++) {
|
||||
valuesLong2[i] = random.nextLong();
|
||||
}
|
||||
|
||||
valuesInt1 = new int[128];
|
||||
valuesInt2 = new int[128];
|
||||
for (int i = 0; i < valuesInt1.length; i++) {
|
||||
valuesInt1[i] = random.nextInt();
|
||||
}
|
||||
for (int i = 0; i < valuesInt2.length; i++) {
|
||||
valuesInt2[i] = random.nextInt();
|
||||
}
|
||||
valueLong1 = random.nextLong();
|
||||
valueLong2 = random.nextLong();
|
||||
valueInt1 = random.nextInt();
|
||||
valueInt2 = random.nextInt();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkAndTestFusableInt(Blackhole bh) {
|
||||
for (int i = 0; i < valuesInt1.length; i++) {
|
||||
int value1 = valuesInt1[i];
|
||||
int value2 = valuesInt2[i];
|
||||
int withAnd1 = value1 & 0xF;
|
||||
int withAnd2 = value2 & 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkAndTestFusableLong(Blackhole bh) {
|
||||
for (int i = 0; i < valuesLong1.length; i++) {
|
||||
long value1 = valuesLong1[i];
|
||||
long value2 = valuesLong2[i];
|
||||
long withAnd1 = value1 & 0xFFFFFFFFFFL;
|
||||
long withAnd2 = value2 & 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkOrTestFusableInt(Blackhole bh) {
|
||||
for (int i = 0; i < valuesInt1.length; i++) {
|
||||
int value1 = valuesInt1[i];
|
||||
int value2 = valuesInt2[i];
|
||||
int withAnd1 = value1 | 0xF;
|
||||
int withAnd2 = value2 | 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkOrTestFusableLong(Blackhole bh) {
|
||||
for (int i = 0; i < valuesLong1.length; i++) {
|
||||
long value1 = valuesLong1[i];
|
||||
long value2 = valuesLong2[i];
|
||||
long withAnd1 = value1 | 0xFFFFFFFFFFL;
|
||||
long withAnd2 = value2 | 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkXorTestFusableInt(Blackhole bh) {
|
||||
for (int i = 0; i < valuesInt1.length; i++) {
|
||||
int value1 = valuesInt1[i];
|
||||
int value2 = valuesInt2[i];
|
||||
int withAnd1 = value1 ^ 0xF;
|
||||
int withAnd2 = value2 ^ 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkXorTestFusableLong(Blackhole bh) {
|
||||
for (int i = 0; i < valuesLong1.length; i++) {
|
||||
long value1 = valuesLong1[i];
|
||||
long value2 = valuesLong2[i];
|
||||
long withAnd1 = value1 ^ 0xFFFFFFFFFFL;
|
||||
long withAnd2 = value2 ^ 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkAndTestFusableIntSingle(Blackhole bh) {
|
||||
int withAnd1 = valueInt1 & 0xF;
|
||||
int withAnd2 = valueInt2 & 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkAndTestFusableLongSingle(Blackhole bh) {
|
||||
long withAnd1 = valueLong1 & 0xFFFFFFFFFFL;
|
||||
long withAnd2 = valueLong2 & 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkOrTestFusableIntSingle(Blackhole bh) {
|
||||
int withAnd1 = valueInt1 | 0xF;
|
||||
int withAnd2 = valueInt2 | 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkOrTestFusableLongSingle(Blackhole bh) {
|
||||
long withAnd1 = valueLong1 | 0xFFFFFFFFFFL;
|
||||
long withAnd2 = valueLong2 | 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkXorTestFusableIntSingle(Blackhole bh) {
|
||||
int withAnd1 = valueInt1 ^ 0xF;
|
||||
int withAnd2 = valueInt2 ^ 0xF;
|
||||
|
||||
bh.consume(withAnd1 > 0x0 && withAnd2 > 0x0 && withAnd1 < 0xF && withAnd2 < 0xF);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void benchmarkXorTestFusableLongSingle(Blackhole bh) {
|
||||
long withAnd1 = valueLong1 ^ 0xFFFFFFFFFFL;
|
||||
long withAnd2 = valueLong2 ^ 0xFFFFFFFFFFL;
|
||||
|
||||
bh.consume(withAnd1 > 0x0L && withAnd2 > 0x0L && withAnd1 < 0xFFFFFFFFFFL && withAnd2 < 0xFFFFFFFFFFL);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user