8240615: is_power_of_2() has Undefined Behaviour and is inconsistent

Reviewed-by: jrose, redestad
This commit is contained in:
Andrew Haley 2020-03-10 10:49:01 -04:00
parent 534331f0a1
commit 661c073594
4 changed files with 16 additions and 12 deletions
src/hotspot
cpu
share/utilities
test/hotspot/gtest/utilities

@ -14936,7 +14936,7 @@ instruct cmpI_branch_sign(cmpOpLtGe cmp, iRegIorL2I op1, immI0 op2, label labl)
instruct cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
match(If cmp (CmpL (AndL op1 op2) op3));
predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
predicate(is_power_of_2((julong)n->in(2)->in(1)->in(2)->get_long()));
effect(USE labl);
ins_cost(BRANCH_COST);
@ -14944,7 +14944,7 @@ instruct cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label la
ins_encode %{
Label* L = $labl$$label;
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
int bit = exact_log2($op2$$constant);
int bit = exact_log2_long($op2$$constant);
__ tbr(cond, $op1$$Register, bit, *L);
%}
ins_pipe(pipe_cmp_branch);
@ -14953,7 +14953,7 @@ instruct cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label la
instruct cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
match(If cmp (CmpI (AndI op1 op2) op3));
predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
predicate(is_power_of_2((juint)n->in(2)->in(1)->in(2)->get_int()));
effect(USE labl);
ins_cost(BRANCH_COST);
@ -14961,7 +14961,7 @@ instruct cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3, lab
ins_encode %{
Label* L = $labl$$label;
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
int bit = exact_log2($op2$$constant);
int bit = exact_log2((juint)$op2$$constant);
__ tbr(cond, $op1$$Register, bit, *L);
%}
ins_pipe(pipe_cmp_branch);
@ -15001,7 +15001,7 @@ instruct far_cmpI_branch_sign(cmpOpLtGe cmp, iRegIorL2I op1, immI0 op2, label la
instruct far_cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, label labl) %{
match(If cmp (CmpL (AndL op1 op2) op3));
predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_long()));
predicate(is_power_of_2((julong)n->in(2)->in(1)->in(2)->get_long()));
effect(USE labl);
ins_cost(BRANCH_COST);
@ -15009,7 +15009,7 @@ instruct far_cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, labe
ins_encode %{
Label* L = $labl$$label;
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
int bit = exact_log2($op2$$constant);
int bit = exact_log2_long($op2$$constant);
__ tbr(cond, $op1$$Register, bit, *L, /*far*/true);
%}
ins_pipe(pipe_cmp_branch);
@ -15017,7 +15017,7 @@ instruct far_cmpL_branch_bit(cmpOpEqNe cmp, iRegL op1, immL op2, immL0 op3, labe
instruct far_cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3, label labl) %{
match(If cmp (CmpI (AndI op1 op2) op3));
predicate(is_power_of_2(n->in(2)->in(1)->in(2)->get_int()));
predicate(is_power_of_2((juint)n->in(2)->in(1)->in(2)->get_int()));
effect(USE labl);
ins_cost(BRANCH_COST);
@ -15025,7 +15025,7 @@ instruct far_cmpI_branch_bit(cmpOpEqNe cmp, iRegIorL2I op1, immI op2, immI0 op3,
ins_encode %{
Label* L = $labl$$label;
Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode;
int bit = exact_log2($op2$$constant);
int bit = exact_log2((juint)$op2$$constant);
__ tbr(cond, $op1$$Register, bit, *L, /*far*/true);
%}
ins_pipe(pipe_cmp_branch);

@ -3120,7 +3120,7 @@ operand immL32()
operand immL_Pow2()
%{
predicate(is_power_of_2(n->get_long()));
predicate(is_power_of_2((julong)n->get_long()));
match(ConL);
op_cost(15);
@ -3130,7 +3130,7 @@ operand immL_Pow2()
operand immL_NotPow2()
%{
predicate(is_power_of_2(~n->get_long()));
predicate(is_power_of_2((julong)~n->get_long()));
match(ConL);
op_cost(15);
@ -10029,7 +10029,7 @@ instruct btsL_mem_imm(memory dst, immL_Pow2 con, rFlagsReg cr)
ins_cost(125);
format %{ "btsq $dst, log2($con)\t# long" %}
ins_encode %{
__ btsq($dst$$Address, log2_long($con$$constant));
__ btsq($dst$$Address, log2_long((julong)$con$$constant));
%}
ins_pipe(ialu_mem_imm);
%}

@ -36,7 +36,7 @@
template <typename T>
bool is_power_of_2(T x) {
return (x != T(0)) && ((x & (x - 1)) == T(0));
return (x > T(0)) && ((x & (x - 1)) == T(0));
}
// Log2 of a power of 2

@ -36,6 +36,10 @@ template <typename T> static void test_is_power_of_2() {
EXPECT_FALSE(is_power_of_2(T(0)));
EXPECT_FALSE(is_power_of_2(~T(0)));
if (IsSigned<T>::value) {
EXPECT_FALSE(is_power_of_2(std::numeric_limits<T>::min()));
}
// Test true
for (T i = max_pow2<T>(); i > 0; i = (i >> 1)) {
EXPECT_TRUE(is_power_of_2(i)) << "value = " << T(i);