Skip to content
Permalink
Browse files
8252188: Crash in OrINode::Ideal(PhaseGVN*, bool)+0x8b9
Reviewed-by: vlivanov, thartmann, jbhateja
  • Loading branch information
Vladimir Kozlov committed Sep 19, 2020
1 parent 224a30f commit 1438ce097f4b327570504066a3f999163802a14f
Showing 7 changed files with 996 additions and 378 deletions.
@@ -743,41 +743,47 @@ Node* OrINode::Identity(PhaseGVN* phase) {
return AddNode::Identity(phase);
}

Node *OrINode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Find shift value for Integer or Long OR.
Node* rotate_shift(PhaseGVN* phase, Node* lshift, Node* rshift, int mask) {
// val << norm_con_shift | val >> ({32|64} - norm_con_shift) => rotate_left val, norm_con_shift
const TypeInt* lshift_t = phase->type(lshift)->isa_int();
const TypeInt* rshift_t = phase->type(rshift)->isa_int();
if (lshift_t != NULL && lshift_t->is_con() &&
rshift_t != NULL && rshift_t->is_con() &&
((lshift_t->get_con() & mask) == ((mask + 1) - (rshift_t->get_con() & mask)))) {
return phase->intcon(lshift_t->get_con() & mask);
}
// val << var_shift | val >> ({0|32|64} - var_shift) => rotate_left val, var_shift
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift && rshift->in(1)->is_Con()){
const TypeInt* shift_t = phase->type(rshift->in(1))->isa_int();
if (shift_t != NULL && shift_t->is_con() &&
(shift_t->get_con() == 0 || shift_t->get_con() == (mask + 1))) {
return lshift;
}
}
return NULL;
}

Node* OrINode::Ideal(PhaseGVN* phase, bool can_reshape) {
int lopcode = in(1)->Opcode();
int ropcode = in(2)->Opcode();
if (Matcher::match_rule_supported(Op_RotateLeft) &&
lopcode == Op_LShiftI && ropcode == Op_URShiftI && in(1)->in(1) == in(2)->in(1)) {
Node *lshift = in(1)->in(2);
Node *rshift = in(2)->in(2);
// val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val , norm_con_shift
if (lshift->is_Con() && rshift->is_Con() &&
((lshift->get_int() & 0x1F) == (32 - (rshift->get_int() & 0x1F)))) {
return new RotateLeftNode(in(1)->in(1),
phase->intcon(lshift->get_int() & 0x1F), TypeInt::INT);
}
// val << var_shift | val >> (0/32 - var_shift) => rotate_left val , var_shift
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
rshift->in(1)->is_Con() &&
(rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 32)) {
return new RotateLeftNode(in(1)->in(1), lshift, TypeInt::INT);
Node* lshift = in(1)->in(2);
Node* rshift = in(2)->in(2);
Node* shift = rotate_shift(phase, lshift, rshift, 0x1F);
if (shift != NULL) {
return new RotateLeftNode(in(1)->in(1), shift, TypeInt::INT);
}
return NULL;
}
if (Matcher::match_rule_supported(Op_RotateRight) &&
lopcode == Op_URShiftI && ropcode == Op_LShiftI && in(1)->in(1) == in(2)->in(1)) {
Node *rshift = in(1)->in(2);
Node *lshift = in(2)->in(2);
// val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val , norm_con_shift
if (rshift->is_Con() && lshift->is_Con() &&
((rshift->get_int() & 0x1F) == (32 - (lshift->get_int() & 0x1F)))) {
return new RotateRightNode(in(1)->in(1),
phase->intcon(rshift->get_int() & 0x1F), TypeInt::INT);
}
// val >> var_shift | val << (0/32 - var_shift) => rotate_right val , var_shift
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
lshift->in(1)->is_Con() &&
(lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 32)) {
return new RotateRightNode(in(1)->in(1), rshift, TypeInt::INT);
Node* shift = rotate_shift(phase, rshift, lshift, 0x1F);
if (shift != NULL) {
return new RotateRightNode(in(1)->in(1), shift, TypeInt::INT);
}
}
return NULL;
@@ -824,42 +830,27 @@ Node* OrLNode::Identity(PhaseGVN* phase) {
return AddNode::Identity(phase);
}

Node *OrLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* OrLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
int lopcode = in(1)->Opcode();
int ropcode = in(2)->Opcode();
if (Matcher::match_rule_supported(Op_RotateLeft) &&
lopcode == Op_LShiftL && ropcode == Op_URShiftL && in(1)->in(1) == in(2)->in(1)) {
Node *lshift = in(1)->in(2);
Node *rshift = in(2)->in(2);
// val << norm_con_shift | val >> (64 - norm_con_shift) => rotate_left val , norm_con_shift
if (lshift->is_Con() && rshift->is_Con() &&
((lshift->get_int() & 0x3F) == (64 - (rshift->get_int() & 0x3F)))) {
return new RotateLeftNode(in(1)->in(1),
phase->intcon(lshift->get_int() & 0x3F), TypeLong::LONG);
}
// val << var_shift | val >> (0/64 - var_shift) => rotate_left val , var_shift
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
rshift->in(1)->is_Con() &&
(rshift->in(1)->get_int() == 0 || rshift->in(1)->get_int() == 64)) {
return new RotateLeftNode(in(1)->in(1), lshift, TypeLong::LONG);
}
Node* lshift = in(1)->in(2);
Node* rshift = in(2)->in(2);
Node* shift = rotate_shift(phase, lshift, rshift, 0x3F);
if (shift != NULL) {
return new RotateLeftNode(in(1)->in(1), shift, TypeLong::LONG);
}
return NULL;
}
if (Matcher::match_rule_supported(Op_RotateRight) &&
lopcode == Op_URShiftL && ropcode == Op_LShiftL && in(1)->in(1) == in(2)->in(1)) {
Node *rshift = in(1)->in(2);
Node *lshift = in(2)->in(2);
// val >> norm_con_shift | val << (64 - norm_con_shift) => rotate_right val , norm_con_shift
if (rshift->is_Con() && lshift->is_Con() &&
((rshift->get_int() & 0x3F) == (64 - (lshift->get_int() & 0x3F)))) {
return new RotateRightNode(in(1)->in(1),
phase->intcon(rshift->get_int() & 0x3F), TypeLong::LONG);
}
// val >> var_shift | val << (0/64 - var_shift) => rotate_right val , var_shift
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
lshift->in(1)->is_Con() &&
(lshift->in(1)->get_int() == 0 || lshift->in(1)->get_int() == 64)) {
return new RotateRightNode(in(1)->in(1), rshift, TypeLong::LONG);
}
Node* rshift = in(1)->in(2);
Node* lshift = in(2)->in(2);
Node* shift = rotate_shift(phase, rshift, lshift, 0x3F);
if (shift != NULL) {
return new RotateRightNode(in(1)->in(1), shift, TypeLong::LONG);
}
}
return NULL;
}
@@ -835,46 +835,33 @@ MacroLogicVNode* MacroLogicVNode::make(PhaseGVN& gvn, Node* in1, Node* in2, Node

Node* VectorNode::degenerate_vector_rotate(Node* src, Node* cnt, bool is_rotate_left,
int vlen, BasicType bt, PhaseGVN* phase) {
int shiftLOpc;
int shiftROpc;
Node* shiftLCnt = NULL;
Node* shiftRCnt = NULL;
assert(bt == T_INT || bt == T_LONG, "sanity");
const TypeVect* vt = TypeVect::make(bt, vlen);

int shift_mask = (bt == T_INT) ? 0x1F : 0x3F;
int shiftLOpc = (bt == T_INT) ? Op_LShiftI : Op_LShiftL;
int shiftROpc = (bt == T_INT) ? Op_URShiftI: Op_URShiftL;

// Compute shift values for right rotation and
// later swap them in case of left rotation.
if (cnt->is_Con()) {
Node* shiftRCnt = NULL;
Node* shiftLCnt = NULL;
if (cnt->is_Con() && cnt->bottom_type()->isa_int()) {
// Constant shift case.
if (bt == T_INT) {
int shift = cnt->get_int() & 31;
shiftRCnt = phase->intcon(shift);
shiftLCnt = phase->intcon(32 - shift);
shiftLOpc = Op_LShiftI;
shiftROpc = Op_URShiftI;
} else {
int shift = cnt->get_int() & 63;
shiftRCnt = phase->intcon(shift);
shiftLCnt = phase->intcon(64 - shift);
shiftLOpc = Op_LShiftL;
shiftROpc = Op_URShiftL;
}
int shift = cnt->get_int() & shift_mask;
shiftRCnt = phase->intcon(shift);
shiftLCnt = phase->intcon(shift_mask + 1 - shift);
} else {
// Variable shift case.
assert(VectorNode::is_invariant_vector(cnt), "Broadcast expected");
cnt = cnt->in(1);
if (bt == T_INT) {
shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(31)));
shiftLCnt = phase->transform(new SubINode(phase->intcon(32), shiftRCnt));
shiftLOpc = Op_LShiftI;
shiftROpc = Op_URShiftI;
} else {
if (bt == T_LONG) {
// Shift count vector for Rotate vector has long elements too.
assert(cnt->Opcode() == Op_ConvI2L, "ConvI2L expected");
cnt = cnt->in(1);
shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(63)));
shiftLCnt = phase->transform(new SubINode(phase->intcon(64), shiftRCnt));
shiftLOpc = Op_LShiftL;
shiftROpc = Op_URShiftL;
}
shiftRCnt = phase->transform(new AndINode(cnt, phase->intcon(shift_mask)));
shiftLCnt = phase->transform(new SubINode(phase->intcon(shift_mask + 1), shiftRCnt));
}

// Swap the computed left and right shift counts.
@@ -908,86 +895,3 @@ Node* RotateRightVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
return NULL;
}

Node* OrVNode::Ideal(PhaseGVN* phase, bool can_reshape) {
int lopcode = in(1)->Opcode();
int ropcode = in(2)->Opcode();
const TypeVect* vt = bottom_type()->is_vect();
int vec_len = vt->length();
BasicType bt = vt->element_basic_type();

// Vector Rotate operations inferencing, this will be useful when vector
// operations are created via non-SLP route i.e. (VectorAPI).
if (Matcher::match_rule_supported_vector(Op_RotateLeftV, vec_len, bt) &&
((ropcode == Op_LShiftVI && lopcode == Op_URShiftVI) ||
(ropcode == Op_LShiftVL && lopcode == Op_URShiftVL)) &&
in(1)->in(1) == in(2)->in(1)) {
assert(Op_RShiftCntV == in(1)->in(2)->Opcode(), "LShiftCntV operand expected");
assert(Op_LShiftCntV == in(2)->in(2)->Opcode(), "RShiftCntV operand expected");
Node* lshift = in(1)->in(2)->in(1);
Node* rshift = in(2)->in(2)->in(1);
int mod_val = bt == T_LONG ? 64 : 32;
int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
// val >> norm_con_shift | val << (32 - norm_con_shift) => rotate_right val ,
// norm_con_shift
if (lshift->is_Con() && rshift->is_Con() &&
((lshift->get_int() & shift_mask) ==
(mod_val - (rshift->get_int() & shift_mask)))) {
return new RotateRightVNode(
in(1)->in(1), phase->intcon(lshift->get_int() & shift_mask), vt);
}
if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
lshift->in(2)->get_int() == (mod_val - 1) &&
rshift->in(2)->get_int() == (mod_val - 1)) {
lshift = lshift->in(1);
rshift = rshift->in(1);
// val << var_shift | val >> (0/32 - var_shift) => rotate_left val ,
// var_shift
if (lshift->Opcode() == Op_SubI && lshift->in(2) == rshift &&
lshift->in(1)->is_Con() &&
(lshift->in(1)->get_int() == 0 ||
lshift->in(1)->get_int() == mod_val)) {
Node* rotate_cnt = phase->transform(new ReplicateINode(rshift, vt));
return new RotateLeftVNode(in(1)->in(1), rotate_cnt, vt);
}
}
}

if (Matcher::match_rule_supported_vector(Op_RotateRightV, vec_len, bt) &&
((ropcode == Op_URShiftVI && lopcode == Op_LShiftVI) ||
(ropcode == Op_URShiftVL && lopcode == Op_LShiftVL)) &&
in(1)->in(1) == in(2)->in(1)) {
assert(Op_LShiftCntV == in(1)->in(2)->Opcode(), "RShiftCntV operand expected");
assert(Op_RShiftCntV == in(2)->in(2)->Opcode(), "LShiftCntV operand expected");
Node* rshift = in(1)->in(2)->in(1);
Node* lshift = in(2)->in(2)->in(1);
int mod_val = bt == T_LONG ? 64 : 32;
int shift_mask = bt == T_LONG ? 0x3F : 0x1F;
// val << norm_con_shift | val >> (32 - norm_con_shift) => rotate_left val
// , norm_con_shift
if (rshift->is_Con() && lshift->is_Con() &&
((rshift->get_int() & shift_mask) ==
(mod_val - (lshift->get_int() & shift_mask)))) {
return new RotateLeftVNode(
in(1)->in(1), phase->intcon(rshift->get_int() & shift_mask), vt);
}
if (lshift->Opcode() == Op_AndI && rshift->Opcode() == Op_AndI &&
lshift->in(2)->is_Con() && rshift->in(2)->is_Con() &&
rshift->in(2)->get_int() == (mod_val - 1) &&
lshift->in(2)->get_int() == (mod_val - 1)) {
rshift = rshift->in(1);
lshift = lshift->in(1);
// val >> var_shift | val << (0/32 - var_shift) => rotate_right val ,
// var_shift
if (rshift->Opcode() == Op_SubI && rshift->in(2) == lshift &&
rshift->in(1)->is_Con() &&
(rshift->in(1)->get_int() == 0 ||
rshift->in(1)->get_int() == mod_val)) {
Node* rotate_cnt = phase->transform(new ReplicateINode(lshift, vt));
return new RotateRightVNode(in(1)->in(1), rotate_cnt, vt);
}
}
}
return NULL;
}

@@ -624,7 +624,6 @@ class OrVNode : public VectorNode {
public:
OrVNode(Node* in1, Node* in2, const TypeVect* vt) : VectorNode(in1,in2,vt) {}
virtual int Opcode() const;
Node* Ideal(PhaseGVN* phase, bool can_reshape);
};

//------------------------------XorVNode---------------------------------------

1 comment on commit 1438ce0

@bridgekeeper
Copy link

@bridgekeeper bridgekeeper bot commented on 1438ce0 Sep 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.