Skip to content

Commit

Permalink
x ^ 0 opt
Browse files Browse the repository at this point in the history
  • Loading branch information
SkiFoD authored Mar 28, 2022
1 parent c3c0223 commit 071e772
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 24 deletions.
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6507,6 +6507,7 @@ class Compiler
GenTree* fgOptimizeAddition(GenTreeOp* add);
GenTree* fgOptimizeMultiply(GenTreeOp* mul);
GenTree* fgOptimizeBitwiseAnd(GenTreeOp* andOp);
GenTree* fgOptimizeBitwiseXor(GenTreeOp* xorOp);
GenTree* fgPropagateCommaThrow(GenTree* parent, GenTreeOp* commaThrow, GenTreeFlags precedingSideEffects);
GenTree* fgMorphRetInd(GenTreeUnOp* tree);
GenTree* fgMorphModToSubMulDiv(GenTreeOp* tree);
Expand Down
73 changes: 49 additions & 24 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13752,6 +13752,10 @@ GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree)
{
optimizedTree = fgOptimizeBitwiseAnd(tree);
}
else if (tree->OperIs(GT_XOR))
{
optimizedTree = fgOptimizeBitwiseXor(tree);
}

if (optimizedTree != nullptr)
{
Expand Down Expand Up @@ -14189,6 +14193,51 @@ GenTree* Compiler::fgOptimizeRelationalComparisonWithCasts(GenTreeOp* cmp)
return cmp;
}

// fgOptimizeBitwiseXor: optimizes the "xor" operation.
//
// Arguments:
// xorOp - the GT_XOR tree to optimize.
//
// Return Value:
// The optimized tree, currently always a local variable, in case any transformations
// were performed. Otherwise, "nullptr", guaranteeing no state change.
//
GenTree* Compiler::fgOptimizeBitwiseXor(GenTreeOp* xorOp)
{
assert(xorOp->OperIs(GT_XOR));
assert(!optValnumCSE_phase);

GenTree* op1 = xorOp->gtGetOp1();
GenTree* op2 = xorOp->gtGetOp2();

if (op2->IsIntegralConst(0))
{
/* "x ^ 0" is "x" */
DEBUG_DESTROY_NODE(xorOp, op2);
return op1;
}
else if (op2->IsIntegralConst(-1))
{
/* "x ^ -1" is "~x" */
xorOp->ChangeOper(GT_NOT);
xorOp->gtOp2 = nullptr;
DEBUG_DESTROY_NODE(op2);

return xorOp;
}
else if (op2->IsIntegralConst(1) && op1->OperIsCompare())
{
/* "binaryVal ^ 1" is "!binaryVal" */
gtReverseCond(op1);
DEBUG_DESTROY_NODE(op2);
DEBUG_DESTROY_NODE(xorOp);

return op1;
}

return nullptr;
}

//------------------------------------------------------------------------
// fgPropagateCommaThrow: propagate a "comma throw" up the tree.
//
Expand Down Expand Up @@ -14581,30 +14630,6 @@ GenTree* Compiler::fgMorphSmpOpOptional(GenTreeOp* tree)

break;

case GT_XOR:

if (!optValnumCSE_phase)
{
/* "x ^ -1" is "~x" */

if (op2->IsIntegralConst(-1))
{
tree->ChangeOper(GT_NOT);
tree->gtOp2 = nullptr;
DEBUG_DESTROY_NODE(op2);
}
else if (op2->IsIntegralConst(1) && op1->OperIsCompare())
{
/* "binaryVal ^ 1" is "!binaryVal" */
gtReverseCond(op1);
DEBUG_DESTROY_NODE(op2);
DEBUG_DESTROY_NODE(tree);
return op1;
}
}

break;

case GT_INIT_VAL:
// Initialization values for initBlk have special semantics - their lower
// byte is used to fill the struct. However, we allow 0 as a "bare" value,
Expand Down

0 comments on commit 071e772

Please sign in to comment.