Request for review (M): 7029017 Additional architecture support for c2 compiler
Vladimir Kozlov
vladimir.kozlov at oracle.com
Wed Mar 23 12:45:39 PDT 2011
Here is another suggestion for you. Use final_graph_reshaping to mask shift
count (in final_graph_reshaping_impl()):
case Op_LShiftI:
case Op_RShiftI:
case Op_URShiftI:
case Op_LShiftL:
case Op_RShiftL:
case Op_URShiftL:
if (Matcher::need_masked_shift_count) {
Node* in2 = n->in(2);
juint mask = (n->bottom_type() == TypeInt::INT) ? (BitsPerInt - 1) :
(BitsPerLong - 1);
const TypeInt* t = in2->find_int_type();
if (t != NULL && t->is_con()) {
juint shift = t->get_con();
if (shift > mask) { // Unsigned cmp
Compile* C = Compile::current();
n->set_req(2, ConNode::make(C, TypeInt::make(shift & mask)));
}
} else {
if (t == NULL || t->_lo < 0 || t->_hi > mask) {
Compile* C = Compile::current();
Node* shift = new (C, 3) AndINode(in2, ConNode::make(C,
TypeInt::make(mask)));
n->set_req(2, shift);
}
}
if (in2->outcnt() == 0) { // Remove dead node
in2->disconnect_inputs(NULL);
}
}
break;
Vladimir
Vladimir Kozlov wrote:
> What I meant is:
>
> in your platform .ad file you asign 'true' and in others 'false':
>
> const bool Matcher::need_masked_shift_count = true;
>
> in matchser.hpp:
>
> + static const bool need_masked_shift_count;
>
> in mulnode.cpp:
>
> + if (Matcher::need_masked_shift_count) {
>
>
> I am concern about masking during ideal transformation. It affects all
> platforms and you will convert a negative value to positive which may
> produce a different result since it may affect some ideal
> transformations. I would suggest to do it in .ad file.
>
> instruct sarI_reg_imm(iRegI dst, iRegI src1, immI src2) %{
> match(Set dst (RShiftI src1 src2));
> format %{ "SRA $src1,$src2,$dst" %}
> ins_encode %{
> int shift = ($src2$$constant) & (BitsPerInt - 1);
> __ sra($src1$$Register, shift, $dst$$Register);
> %}
> ins_pipe(ialu_reg_imm);
> %}
>
>
> And for variable shift you can use predicate in .ad file to avoid AND:
>
> // Version without AND
> instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
> predicate(n->in(2)->is_shift(BitsPerInt - 1));
>
> // Version with AND
> instruct sarI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{
> predicate(!n->in(2)->is_shift(BitsPerInt - 1));
> match(Set dst (RShiftI src1 src2));
>
> and in node.hpp
>
> is_shift(int mask) {
> const TypeInt* t = find_int_type();
> return (t != NULL) && t->_lo >= 0 && t->_hi <= mask;
> }
>
>
> Here are few comments for future C2 code modification.
> Don't do assignment in the condition code:
>
> + const TypeInt *t;
> + // avoid infinite loop of shift transformations
> + if( !(t = phase->type(in2)->isa_int()) || t->_lo < 0 || t->_hi > m ) {
>
> Use "if (a)" spacing instead of "if( a )".
>
> Also you should not modify dead node, it is useless:
>
> - if( t == Type::TOP ) return NULL; // Right input is dead
> + if( t == Type::TOP ) return do_mask_shift(phase, BitsPerInt - 1); //
> Right input is dead
>
>
> Vladimir
>
> Roland Westrelin wrote:
>> Hi Vladimir,
>>
>>> Did you consider to use Matcher property instead of new flag and new
>>> ideal node
>>> code? See how we do Matcher::clone_shift_expressions.
>>
>> I would like the extra and operations to be optimized out when
>> possible. That won't happen if I do the work at the matcher level, right?
>>
>> Roland.
More information about the hotspot-compiler-dev
mailing list