Skip to content

Commit

Permalink
JIT: handle more cases for MOD/DIV -> UMOD/UDIV transformation (#62394)
Browse files Browse the repository at this point in the history
* Introduce IsNeverNegative

* Address feedback

* Apply suggestions from code review

Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com>

* Address feedback

* fix build on x86

Co-authored-by: SingleAccretion <62474226+SingleAccretion@users.noreply.github.com>
  • Loading branch information
EgorBo and SingleAccretion authored Dec 17, 2021
1 parent 5a5d379 commit a6de632
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 10 deletions.
23 changes: 23 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21681,3 +21681,26 @@ bool GenTree::IsInvariant() const
GenTree* lclVarTree = nullptr;
return OperIsConst() || Compiler::impIsAddressInLocal(this, &lclVarTree);
}

//------------------------------------------------------------------------
// IsNeverNegative: returns true if the given tree is known to be never
// negative, i. e. the upper bit will always be zero.
// Only valid for integral types.
//
// Arguments:
// comp - Compiler object, needed for IntegralRange::ForNode
//
// Return Value:
// true if the given tree is known to be never negative
//
bool GenTree::IsNeverNegative(Compiler* comp) const
{
assert(varTypeIsIntegral(this));

if (IsIntegralConst())
{
return AsIntConCommon()->IntegralValue() >= 0;
}
// TODO-Casts: extend IntegralRange to handle constants
return IntegralRange::ForNode((GenTree*)this, comp).IsPositive();
}
2 changes: 2 additions & 0 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -2260,6 +2260,8 @@ struct GenTree

bool IsInvariant() const;

bool IsNeverNegative(Compiler* comp) const;

bool IsReuseRegVal() const
{
// This can be extended to non-constant nodes, but not to local or indir nodes.
Expand Down
18 changes: 8 additions & 10 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11159,13 +11159,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
}
}

// array.Length is always positive so GT_DIV can be changed to GT_UDIV
// if op2 is a positive cns
if (!optValnumCSE_phase && op1->OperIs(GT_ARR_LENGTH) && op2->IsIntegralConst() &&
op2->AsIntCon()->IconValue() >= 2) // for 0 and 1 it doesn't matter if it's UDIV or DIV
// Convert DIV to UDIV if boths op1 and op2 are known to be never negative
if (!gtIsActiveCSE_Candidate(tree) && varTypeIsIntegral(tree) && op1->IsNeverNegative(this) &&
op2->IsNeverNegative(this))
{
assert(tree->OperIs(GT_DIV));
tree->ChangeOper(GT_UDIV);
tree->ChangeOper(GT_UDIV, GenTree::PRESERVE_VN);
return fgMorphSmpOp(tree, mac);
}

Expand Down Expand Up @@ -11228,13 +11227,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac)
goto USE_HELPER_FOR_ARITH;
}

// array.Length is always positive so GT_DIV can be changed to GT_UDIV
// if op2 is a positive cns
if (!optValnumCSE_phase && op1->OperIs(GT_ARR_LENGTH) && op2->IsIntegralConst() &&
op2->AsIntCon()->IconValue() >= 2) // for 0 and 1 it doesn't matter if it's UMOD or MOD
// Convert MOD to UMOD if boths op1 and op2 are known to be never negative
if (!gtIsActiveCSE_Candidate(tree) && varTypeIsIntegral(tree) && op1->IsNeverNegative(this) &&
op2->IsNeverNegative(this))
{
assert(tree->OperIs(GT_MOD));
tree->ChangeOper(GT_UMOD);
tree->ChangeOper(GT_UMOD, GenTree::PRESERVE_VN);
return fgMorphSmpOp(tree, mac);
}

Expand Down

0 comments on commit a6de632

Please sign in to comment.