Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Commutative morph optimizations #64122

Merged
merged 4 commits into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -7122,12 +7122,6 @@ class Compiler

bool optNarrowTree(GenTree* tree, var_types srct, var_types dstt, ValueNumPair vnpNarrow, bool doit);

/**************************************************************************
* Optimization conditions
*************************************************************************/

bool optAvoidIntMult(void);

protected:
// The following is the upper limit on how many expressions we'll keep track
// of for the CSE analysis.
Expand Down
16 changes: 0 additions & 16 deletions src/coreclr/jit/compiler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3578,22 +3578,6 @@ inline bool Compiler::LoopDsc::lpArrLenLimit(Compiler* comp, ArrIndex* index) co
return false;
}

/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XX XX
XX Optimization activation rules XX
XX XX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
*/

// should we try to replace integer multiplication with lea/add/shift sequences?
inline bool Compiler::optAvoidIntMult(void)
{
return (compCodeOpt() != SMALL_CODE);
}

/*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Expand Down
66 changes: 39 additions & 27 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13435,28 +13435,6 @@ GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree)
std::swap(tree->gtOp1, tree->gtOp2);
}

if (!optValnumCSE_phase)
{
GenTree* optimizedTree = nullptr;
if (tree->OperIs(GT_ADD))
{
optimizedTree = fgOptimizeAddition(tree);
}
else if (tree->OperIs(GT_MUL))
{
optimizedTree = fgOptimizeMultiply(tree);
}
else if (tree->OperIs(GT_AND))
{
optimizedTree = fgOptimizeBitwiseAnd(tree);
}

if (optimizedTree != nullptr)
{
return optimizedTree;
}
}

if (fgOperIsBitwiseRotationRoot(tree->OperGet()))
{
GenTree* rotationTree = fgRecognizeAndMorphBitwiseRotation(tree);
Expand All @@ -13477,7 +13455,36 @@ GenTree* Compiler::fgOptimizeCommutativeArithmetic(GenTreeOp* tree)

if (varTypeIsIntegralOrI(tree))
{
genTreeOps oldTreeOper = tree->OperGet();
GenTreeOp* optimizedTree = fgMorphCommutative(tree->AsOp());
if (optimizedTree != nullptr)
{
if (!optimizedTree->OperIs(oldTreeOper))
{
// "optimizedTree" could end up being a COMMA.
return optimizedTree;
}

tree = optimizedTree;
}
}

if (!optValnumCSE_phase)
{
GenTree* optimizedTree = nullptr;
if (tree->OperIs(GT_ADD))
{
optimizedTree = fgOptimizeAddition(tree);
}
else if (tree->OperIs(GT_MUL))
{
optimizedTree = fgOptimizeMultiply(tree);
}
else if (tree->OperIs(GT_AND))
{
optimizedTree = fgOptimizeBitwiseAnd(tree);
}

if (optimizedTree != nullptr)
{
return optimizedTree;
Expand Down Expand Up @@ -13529,8 +13536,7 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add)

// Fold (x + 0) - given it won't change the tree type to TYP_REF.
// TODO-Bug: this code will lose the GC-ness of a tree like "native int + byref(0)".
if (op2->IsCnsIntOrI() && (op2->AsIntCon()->IconValue() == 0) &&
((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF)))
if (op2->IsIntegralConst(0) && ((add->TypeGet() == op1->TypeGet()) || !op1->TypeIs(TYP_REF)))
{
if (op2->IsCnsIntOrI() && (op2->AsIntCon()->gtFieldSeq != nullptr) &&
(op2->AsIntCon()->gtFieldSeq != FieldSeqStore::NotAField()))
Expand All @@ -13544,9 +13550,8 @@ GenTree* Compiler::fgOptimizeAddition(GenTreeOp* add)
return op1;
}

// TODO-CQ: this transform preserves VNs and can be enabled outside global morph.
// Note that these transformations are legal for floating-point ADDs as well.
if (opts.OptimizationEnabled() && fgGlobalMorph)
if (opts.OptimizationEnabled())
{
// - a + b = > b - a
// ADD((NEG(a), b) => SUB(b, a)
Expand Down Expand Up @@ -13655,6 +13660,13 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul)
return mul;
}

#ifdef TARGET_XARCH
// Should we try to replace integer multiplication with lea/add/shift sequences?
bool mulShiftOpt = compCodeOpt() != SMALL_CODE;
#else // !TARGET_XARCH
bool mulShiftOpt = false;
#endif // !TARGET_XARCH

size_t abs_mult = (mult >= 0) ? mult : -mult;
size_t lowestBit = genFindLowestBit(abs_mult);
bool changeToShift = false;
Expand Down Expand Up @@ -13697,7 +13709,7 @@ GenTree* Compiler::fgOptimizeMultiply(GenTreeOp* mul)
op2->AsIntConCommon()->SetIconValue(genLog2(abs_mult));
changeToShift = true;
}
else if ((lowestBit > 1) && jitIsScaleIndexMul(lowestBit) && optAvoidIntMult())
else if (mulShiftOpt && (lowestBit > 1) && jitIsScaleIndexMul(lowestBit))
{
int shift = genLog2(lowestBit);
ssize_t factor = abs_mult >> shift;
Expand Down