RFR: 8240615: is_power_of_2() has Undefined Behaviour and is inconsistent

Andrew Haley aph at redhat.com
Fri Mar 6 17:11:20 UTC 2020


On 3/6/20 2:48 PM, Andrew Haley wrote:
>> The predicate for Pow2 and NotPow2 will both be false because of this
>> change. Is that a problem?
> Probably. I'll do some more digging.

The pattern genertates a bitset instruction. It'll generate slightly
less efficient code after my change. Maybe.

It's pretty damm hard to persuade C2 actually to use this pattern, but
this works:

    @Benchmark
    public void test_btsL_mem_imm(BenchmarkState state) {
        for (int i = 0; i < 1000; i += 3) {
            state.array[i] |= 0x4000_0000_0000_0000l;
            state.array[i+1] |= 0x8000_0000_0000_0000l;
            state.array[i+2] |= 0x1000_0000_0000_0000l;
        }
    }

These three |= ops turn into:

  0x00007fe65cc58f40:   bts    QWORD PTR [r8+r10*8+0x10],0x3e;*lastore {reexecute=0 rethrow=0 return_oop=0}
  0x00007fe65cc58f47:   or     QWORD PTR [r8+r10*8+0x18],rdi;*lastore {reexecute=0 rethrow=0 return_oop=0}
  0x00007fe65cc58f4c:   bts    QWORD PTR [r8+r10*8+0x20],0x3c;*lastore {reexecute=0 rethrow=0 return_oop=0}

There is a very slight pessimization in that RDI is now occupied, so
the register pressure is slightly increased, and there's the cost of a
64-bit load immediate operation.

We can get back to the status quo with this patch:

--- a/src/hotspot/cpu/x86/x86_64.ad     Thu Mar 05 17:56:08 2020 +0000
+++ b/src/hotspot/cpu/x86/x86_64.ad     Fri Mar 06 17:06:20 2020 +0000
@@ -3120,7 +3120,7 @@

 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_NotPow2()
 %{
-  predicate(is_power_of_2(~n->get_long()));
+  predicate(is_power_of_2((julong)~n->get_long()));
   match(ConL);

   op_cost(15);

  0x00007fc688bf8010:   bts    QWORD PTR [r10+r8*8+0x10],0x3e;*lastore {reexecute=0 rethrow=0 return_oop=0}
  0x00007fc688bf8017:   bts    QWORD PTR [r10+r8*8+0x18],0x3f;*lastore {reexecute=0 rethrow=0 return_oop=0}
  0x00007fc688bf801e:   bts    QWORD PTR [r10+r8*8+0x20],0x3c;*lastore {reexecute=0 rethrow=0 return_oop=0}

There will be more examples of this, stuff that just works "by
accident". If we want the previous weird behaviour we could explictly
special-case that behaviour and test it. I'd rather not...

-- 
Andrew Haley  (he/him)
Java Platform Lead Engineer
Red Hat UK Ltd. <https://www.redhat.com>
https://keybase.io/andrewhaley
EAC8 43EB D3EF DB98 CC77 2FAD A5CD 6035 332F A671



More information about the hotspot-runtime-dev mailing list