diff -r 7bbaa3c416e7 -r f0312c7d5b37 src/hotspot/cpu/x86/x86_64.ad --- a/src/hotspot/cpu/x86/x86_64.ad Mon Oct 21 19:58:16 2019 +0200 +++ b/src/hotspot/cpu/x86/x86_64.ad Wed Nov 13 11:21:15 2019 +0100 @@ -3116,6 +3116,26 @@ interface(CONST_INTER); %} +operand immL_Pow2() +%{ + predicate(is_power_of_2_long(n->get_long())); + match(ConL); + + op_cost(15); + format %{ %} + interface(CONST_INTER); +%} + +operand immL_NotPow2() +%{ + predicate(is_power_of_2_long(~n->get_long())); + match(ConL); + + op_cost(15); + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate zero operand immL0() %{ @@ -9841,6 +9861,23 @@ ins_pipe(ialu_mem_imm); %} +instruct btrL_mem_imm(memory dst, immL_NotPow2 con, rFlagsReg cr) +%{ + // con should be a pure 64-bit immediate given that not(con) is a power of 2 + // because AND/OR works well enough for 8/32-bit values. + predicate(log2_long(~n->in(3)->in(2)->get_long()) > 30); + + match(Set dst (StoreL dst (AndL (LoadL dst) con))); + effect(KILL cr); + + ins_cost(125); + format %{ "btrq $dst, log2(not($con))\t# long" %} + ins_encode %{ + __ btrq($dst$$Address, log2_long(~$con$$constant)); + %} + ins_pipe(ialu_mem_imm); +%} + // BMI1 instructions instruct andnL_rReg_rReg_mem(rRegL dst, rRegL src1, memory src2, immL_M1 minus_1, rFlagsReg cr) %{ match(Set dst (AndL (XorL src1 minus_1) (LoadL src2))); @@ -10034,6 +10071,23 @@ ins_pipe(ialu_mem_imm); %} +instruct btsL_mem_imm(memory dst, immL_Pow2 con, rFlagsReg cr) +%{ + // con should be a pure 64-bit power of 2 immediate + // because AND/OR works well enough for 8/32-bit values. + predicate(log2_long(n->in(3)->in(2)->get_long()) > 31); + + match(Set dst (StoreL dst (OrL (LoadL dst) con))); + effect(KILL cr); + + ins_cost(125); + format %{ "btsq $dst, log2($con)\t# long" %} + ins_encode %{ + __ btsq($dst$$Address, log2_long($con$$constant)); + %} + ins_pipe(ialu_mem_imm); +%} + // Xor Instructions // Xor Register with Register instruct xorL_rReg(rRegL dst, rRegL src, rFlagsReg cr)