Skip to content

Commit

Permalink
Simple GT_NEG optimization for #13837 (#43921)
Browse files Browse the repository at this point in the history
* Simple arithmetic optimization with GT_NEG

* Skip GT_NEG optimization when an operand is constant. Revert bitwise rotation pattern

* Fixed Value Numbering assert

* Cleaned up code and comments for simple GT_NEG optimization

* Formatting

Co-authored-by: Julie Lee <jeonlee@microsoft.com>
  • Loading branch information
JulieLeeMSFT and ewhapdx committed Nov 6, 2020
1 parent d547916 commit cecbbfb
Showing 1 changed file with 101 additions and 0 deletions.
101 changes: 101 additions & 0 deletions src/coreclr/src/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13387,6 +13387,56 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)

/* No match - exit */
}

// Skip optimization if non-NEG operand is constant.
// Both op1 and op2 are not constant because it was already checked above.
if (opts.OptimizationEnabled() && fgGlobalMorph &&
(((op1->gtFlags & GTF_EXCEPT) == 0) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
{
// a - -b = > a + b
// SUB(a, (NEG(b)) => ADD(a, b)

if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG))
{
// tree: SUB
// op1: a
// op2: NEG
// op2Child: b

GenTree* op2Child = op2->AsOp()->gtOp1; // b
oper = GT_ADD;
tree->SetOper(oper, GenTree::PRESERVE_VN);
tree->AsOp()->gtOp2 = op2Child;

DEBUG_DESTROY_NODE(op2);

op2 = op2Child;
}

// -a - -b = > b - a
// SUB(NEG(a), (NEG(b)) => SUB(b, a)

if (op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG))
{
// tree: SUB
// op1: NEG
// op1Child: a
// op2: NEG
// op2Child: b

GenTree* op1Child = op1->AsOp()->gtOp1; // a
GenTree* op2Child = op2->AsOp()->gtOp1; // b
tree->AsOp()->gtOp1 = op2Child;
tree->AsOp()->gtOp2 = op1Child;

DEBUG_DESTROY_NODE(op1);
DEBUG_DESTROY_NODE(op2);

op1 = op2Child;
op2 = op1Child;
}
}

break;

#ifdef TARGET_ARM64
Expand Down Expand Up @@ -13555,6 +13605,57 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
}
}
}

if (opts.OptimizationEnabled() && fgGlobalMorph &&
(((op1->gtFlags & GTF_EXCEPT) == 0) || ((op2->gtFlags & GTF_EXCEPT) == 0)))
{
// - a + b = > b - a
// ADD((NEG(a), b) => SUB(b, a)

// Skip optimization if non-NEG operand is constant.
if (op1->OperIs(GT_NEG) && !op2->OperIs(GT_NEG) &&
!(op2->IsCnsIntOrI() && varTypeIsIntegralOrI(typ)))
{
// tree: ADD
// op1: NEG
// op2: b
// op1Child: a

GenTree* op1Child = op1->AsOp()->gtOp1; // a
oper = GT_SUB;
tree->SetOper(oper, GenTree::PRESERVE_VN);
tree->AsOp()->gtOp1 = op2;
tree->AsOp()->gtOp2 = op1Child;

DEBUG_DESTROY_NODE(op1);

op1 = op2;
op2 = op1Child;
}

// a + -b = > a - b
// ADD(a, (NEG(b)) => SUB(a, b)

if (!op1->OperIs(GT_NEG) && op2->OperIs(GT_NEG))
{
// a is non cosntant because it was already canonicalized to have
// variable on the left and constant on the right.

// tree: ADD
// op1: a
// op2: NEG
// op2Child: b

GenTree* op2Child = op2->AsOp()->gtOp1; // a
oper = GT_SUB;
tree->SetOper(oper, GenTree::PRESERVE_VN);
tree->AsOp()->gtOp2 = op2Child;

DEBUG_DESTROY_NODE(op2);

op2 = op2Child;
}
}
}
/* See if we can fold GT_MUL by const nodes */
else if (oper == GT_MUL && op2->IsCnsIntOrI() && !optValnumCSE_phase)
Expand Down

0 comments on commit cecbbfb

Please sign in to comment.