mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-02 15:20:27 +00:00
8387184: [PPC64] C1 logic operations should support generic constants
Reviewed-by: rrich, dbriemann
This commit is contained in:
parent
88d111e24e
commit
fa2ca3d087
@ -75,23 +75,46 @@ int Assembler::branch_destination(int inst, int pos) {
|
||||
return r;
|
||||
}
|
||||
|
||||
// Low-level andi-one-instruction-macro.
|
||||
void Assembler::andi(Register a, Register s, const long ui16) {
|
||||
if (is_power_of_2(((unsigned long) ui16)+1)) {
|
||||
// Low-level andi-one-instruction-macro. May clobber CR0.
|
||||
void Assembler::andi(Register a, Register s, julong int_or_long_const) {
|
||||
// Instructions which don't set CR0 are preferred.
|
||||
if (int_or_long_const == 0) {
|
||||
// should not be handled as pow2minus1
|
||||
li(a, 0);
|
||||
} else if (is_power_of_2(int_or_long_const + 1)) {
|
||||
// pow2minus1
|
||||
clrldi(a, s, 64 - log2i_exact((((unsigned long) ui16)+1)));
|
||||
} else if (is_power_of_2((jlong) ui16)) {
|
||||
// pow2
|
||||
rlwinm(a, s, 0, 31 - log2i_exact((jlong) ui16), 31 - log2i_exact((jlong) ui16));
|
||||
} else if (is_power_of_2((jlong)-ui16)) {
|
||||
// negpow2
|
||||
clrrdi(a, s, log2i_exact((jlong)-ui16));
|
||||
clrldi(a, s, 64 - log2i_exact(int_or_long_const + 1));
|
||||
} else if (is_power_of_2(-int_or_long_const)) {
|
||||
// negpow2 (includes (julong)min_jlong)
|
||||
clrrdi(a, s, log2i_exact(-int_or_long_const));
|
||||
} else if (is_uimm((jlong)int_or_long_const, 32) && has_consecutive_ones(int_or_long_const)) {
|
||||
// consecutive ones
|
||||
rlwinm(a, s, 0, count_leading_zeros((uint32_t)int_or_long_const),
|
||||
31 - count_trailing_zeros((uint32_t)int_or_long_const));
|
||||
} else if (is_uimm((jlong)int_or_long_const, 16)) {
|
||||
// side effect: clobbers CR0
|
||||
andi_(a, s, int_or_long_const);
|
||||
} else {
|
||||
assert(is_uimm(ui16, 16), "must be 16-bit unsigned immediate");
|
||||
andi_(a, s, ui16);
|
||||
assert(is_uimm((jlong)int_or_long_const, 32) && (int_or_long_const & 0xFFFF) == 0,
|
||||
"not encodable: " UINT64_FORMAT_X, int_or_long_const);
|
||||
// side effect: clobbers CR0
|
||||
andis_(a, s, int_or_long_const >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if int_or_long_const is supported by Assembler::andi.
|
||||
bool Assembler::andi_supports(julong int_or_long_const) {
|
||||
// 16 bit always possible by andi_ (but other instructions are preferred)
|
||||
if (is_uimm((jlong)int_or_long_const, 16)) return true;
|
||||
|
||||
// special cases 32 bit: higher 16 bit and consecutive ones are supported
|
||||
if (is_uimm((jlong)int_or_long_const, 32) &&
|
||||
((int_or_long_const & 0xFFFF) == 0 || has_consecutive_ones(int_or_long_const))) return true;
|
||||
|
||||
// special cases 64 bit: clrldi, clrrdi
|
||||
return is_power_of_2(int_or_long_const + 1) || is_power_of_2(-int_or_long_const);
|
||||
}
|
||||
|
||||
// RegisterOrConstant version.
|
||||
void Assembler::ld(Register d, RegisterOrConstant roc, Register s1) {
|
||||
if (roc.is_constant()) {
|
||||
|
||||
@ -1048,6 +1048,13 @@ class Assembler : public AbstractAssembler {
|
||||
return (julong)x < maxplus1;
|
||||
}
|
||||
|
||||
// Test if x has exactly one consecutive range of one bits (e.g. 00111000)
|
||||
static bool has_consecutive_ones(julong x) {
|
||||
if (x == max_julong) return true;
|
||||
if (x == 0) return false;
|
||||
return is_power_of_2((x >> count_trailing_zeros(x)) + 1);
|
||||
}
|
||||
|
||||
protected:
|
||||
// helpers
|
||||
|
||||
@ -1606,7 +1613,8 @@ class Assembler : public AbstractAssembler {
|
||||
inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg);
|
||||
|
||||
// PPC 1, section 3.3.11, Fixed-Point Logical Instructions
|
||||
void andi( Register a, Register s, long ui16); // optimized version
|
||||
void andi( Register a, Register s, julong int_or_long_const); // optimized version, may clobber CR0
|
||||
static bool andi_supports(julong int_or_long_const);
|
||||
inline void andi_( Register a, Register s, int ui16);
|
||||
inline void andis_( Register a, Register s, int ui16);
|
||||
inline void ori( Register a, Register s, int ui16);
|
||||
|
||||
@ -1669,26 +1669,40 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr
|
||||
d = dest->as_register_lo();
|
||||
l = left->as_register_lo();
|
||||
}
|
||||
long uimms = (unsigned long)uimm >> 16,
|
||||
uimmss = (unsigned long)uimm >> 32;
|
||||
long uimms = (unsigned long)uimm >> 16;
|
||||
|
||||
switch (code) {
|
||||
case lir_logic_and:
|
||||
if (uimmss != 0 || (uimms != 0 && (uimm & 0xFFFF) != 0) || is_power_of_2(uimm)) {
|
||||
__ andi(d, l, uimm); // special cases
|
||||
} else if (uimms != 0) { __ andis_(d, l, uimms); }
|
||||
else { __ andi_(d, l, uimm); }
|
||||
if (Assembler::andi_supports(uimm)) {
|
||||
__ andi(d, l, uimm); // includes andis_ and special cases
|
||||
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
|
||||
__ load_const_optimized(R0, uimm);
|
||||
__ andr(d, l, R0);
|
||||
}
|
||||
break;
|
||||
|
||||
case lir_logic_or:
|
||||
if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ oris(d, l, uimms); }
|
||||
else { __ ori(d, l, uimm); }
|
||||
if (Assembler::is_uimm(uimm, 16)) {
|
||||
__ ori(d, l, uimm);
|
||||
} else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) {
|
||||
__ oris(d, l, uimms);
|
||||
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
|
||||
__ load_const_optimized(R0, uimm);
|
||||
__ orr(d, l, R0);
|
||||
}
|
||||
break;
|
||||
|
||||
case lir_logic_xor:
|
||||
if (uimm == -1) { __ nand(d, l, l); } // special case
|
||||
else if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ xoris(d, l, uimms); }
|
||||
else { __ xori(d, l, uimm); }
|
||||
if (Assembler::is_uimm(uimm, 16)) {
|
||||
__ xori(d, l, uimm);
|
||||
} else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) {
|
||||
__ xoris(d, l, uimms);
|
||||
} else if (uimm == -1) {
|
||||
__ nand(d, l, l); // special case
|
||||
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
|
||||
__ load_const_optimized(R0, uimm);
|
||||
__ xorr(d, l, R0);
|
||||
}
|
||||
break;
|
||||
|
||||
default: ShouldNotReachHere();
|
||||
|
||||
@ -578,18 +578,13 @@ inline bool can_handle_logic_op_as_uimm(ValueType *type, Bytecodes::Code bc) {
|
||||
Assembler::is_uimm((jlong)((julong)int_or_long_const >> 16), 16)) return true;
|
||||
|
||||
// see Assembler::andi
|
||||
if (bc == Bytecodes::_iand &&
|
||||
(is_power_of_2(int_or_long_const+1) ||
|
||||
is_power_of_2(int_or_long_const) ||
|
||||
is_power_of_2(-int_or_long_const))) return true;
|
||||
if (bc == Bytecodes::_land &&
|
||||
(is_power_of_2((unsigned long)int_or_long_const+1) ||
|
||||
(Assembler::is_uimm(int_or_long_const, 32) && is_power_of_2(int_or_long_const)) ||
|
||||
(int_or_long_const != min_jlong && is_power_of_2(-int_or_long_const)))) return true;
|
||||
if ((bc == Bytecodes::_iand || bc == Bytecodes::_land))
|
||||
return Assembler::andi_supports(int_or_long_const);
|
||||
|
||||
// special case: xor -1
|
||||
if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor) &&
|
||||
int_or_long_const == -1) return true;
|
||||
if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor))
|
||||
return (int_or_long_const == -1);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -9155,61 +9155,14 @@ instruct andI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Left shifted Immediate And
|
||||
instruct andI_reg_immIhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2, flagsRegCR0 cr0) %{
|
||||
instruct andI_reg_immI(iRegIdst dst, iRegIsrc src1, immI src2, flagsRegCR0 cr0) %{
|
||||
match(Set dst (AndI src1 src2));
|
||||
predicate(Assembler::andi_supports((juint)(n->in(2)->get_int())));
|
||||
effect(KILL cr0);
|
||||
format %{ "ANDIS $dst, $src1, $src2.hi" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ andis_($dst$$Register, $src1$$Register, (int)((unsigned short)(($src2$$constant & 0xFFFF0000) >> 16)));
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Immediate And
|
||||
instruct andI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2, flagsRegCR0 cr0) %{
|
||||
match(Set dst (AndI src1 src2));
|
||||
effect(KILL cr0);
|
||||
|
||||
format %{ "ANDI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// FIXME: avoid andi_ ?
|
||||
__ andi_($dst$$Register, $src1$$Register, $src2$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Immediate And where the immediate is a negative power of 2.
|
||||
instruct andI_reg_immInegpow2(iRegIdst dst, iRegIsrc src1, immInegpow2 src2) %{
|
||||
match(Set dst (AndI src1 src2));
|
||||
format %{ "ANDWI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(juint)$src2$$constant));
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct andI_reg_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immIpow2minus1 src2) %{
|
||||
match(Set dst (AndI src1 src2));
|
||||
format %{ "ANDWI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((juint)$src2$$constant + 1u));
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src1, immIpowerOf2 src2) %{
|
||||
match(Set dst (AndI src1 src2));
|
||||
predicate(UseRotateAndMaskInstructionsPPC64);
|
||||
format %{ "ANDWI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
int bitpos = 31 - log2i_exact((juint)$src2$$constant);
|
||||
__ rlwinm($dst$$Register, $src1$$Register, 0, bitpos, bitpos);
|
||||
__ andi($dst$$Register, $src1$$Register, (juint)$src2$$constant); // optimized version
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
@ -9227,50 +9180,27 @@ instruct andL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Immediate And long
|
||||
instruct andL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2, flagsRegCR0 cr0) %{
|
||||
instruct andL_reg_immL(iRegLdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{
|
||||
match(Set dst (AndL src1 src2));
|
||||
predicate(Assembler::andi_supports(n->in(2)->get_long()));
|
||||
effect(KILL cr0);
|
||||
|
||||
format %{ "ANDI $dst, $src1, $src2 \t// long" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
// FIXME: avoid andi_ ?
|
||||
__ andi_($dst$$Register, $src1$$Register, $src2$$constant);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Immediate And Long where the immediate is a negative power of 2.
|
||||
instruct andL_reg_immLnegpow2(iRegLdst dst, iRegLsrc src1, immLnegpow2 src2) %{
|
||||
match(Set dst (AndL src1 src2));
|
||||
format %{ "ANDDI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(julong)$src2$$constant));
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
instruct andL_reg_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immLpow2minus1 src2) %{
|
||||
match(Set dst (AndL src1 src2));
|
||||
format %{ "ANDDI $dst, $src1, $src2" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull));
|
||||
__ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// AndL + ConvL2I.
|
||||
instruct convL2I_andL_reg_immLpow2minus1(iRegIdst dst, iRegLsrc src1, immLpow2minus1 src2) %{
|
||||
instruct convL2I_andL_reg_immL(iRegIdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{
|
||||
match(Set dst (ConvL2I (AndL src1 src2)));
|
||||
ins_cost(DEFAULT_COST);
|
||||
|
||||
format %{ "ANDDI $dst, $src1, $src2 \t// long + l2i" %}
|
||||
predicate(Assembler::andi_supports(n->in(1)->in(2)->get_long()));
|
||||
effect(KILL cr0);
|
||||
format %{ "ANDI $dst, $src1, $src2 \t// long + l2i" %}
|
||||
size(4);
|
||||
ins_encode %{
|
||||
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull));
|
||||
__ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user