Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
44 changes: 24 additions & 20 deletions src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6596,14 +6596,16 @@ bool Lowering::LowerUnsignedDivOrMod(GenTreeOp* divMod)
//
// Arguments:
// node - pointer to the DIV or MOD node
// nextNode - out parameter for the next node in the transformed node sequence that needs to be lowered
//
// Returns:
// nullptr if no transformation is done, or the next node in the transformed node sequence that
// needs to be lowered.
// false if no transformation is done, true if a transformation is done
//
GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
bool Lowering::TryLowerConstIntDivOrMod(GenTree* node, GenTree** nextNode)
{
assert((node->OperGet() == GT_DIV) || (node->OperGet() == GT_MOD));
assert(nextNode != nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be initialized *nextNode = nullptr which should be the case if this method returns false?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a similar TryLowerAndNegativeOne with an out parameter nextNode and we do not set that to nullptr or when we return false.


GenTree* divMod = node;
GenTree* dividend = divMod->gtGetOp1();
GenTree* divisor = divMod->gtGetOp2();
Expand All @@ -6618,22 +6620,23 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
if (divMod->OperIs(GT_MOD) && divisor->IsIntegralConstPow2())
{
LowerModPow2(node);
return node->gtNext;
*nextNode = node->gtNext;
return true;
}
assert(node->OperGet() != GT_MOD);
#endif // TARGET_ARM64

if (!divisor->IsCnsIntOrI())
{
return nullptr; // no transformations to make
return false; // no transformations to make
}

if (dividend->IsCnsIntOrI())
{
// We shouldn't see a divmod with constant operands here but if we do then it's likely
// because optimizations are disabled or it's a case that's supposed to throw an exception.
// Don't optimize this.
return nullptr;
return false;
}

ssize_t divisorValue = divisor->AsIntCon()->IconValue();
Expand All @@ -6649,7 +6652,7 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
// case so optimizing this case would break C# code.

// A runtime check could be used to handle this case but it's probably too rare to matter.
return nullptr;
return false;
}

bool isDiv = divMod->OperGet() == GT_DIV;
Expand All @@ -6661,7 +6664,8 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
// If the divisor is the minimum representable integer value then we can use a compare,
// the result is 1 iff the dividend equals divisor.
divMod->SetOper(GT_EQ);
return node;
*nextNode = node;
return true;
}
}

Expand All @@ -6672,7 +6676,7 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
{
if (comp->opts.MinOpts())
{
return nullptr;
return false;
}

#if defined(TARGET_XARCH) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
Expand Down Expand Up @@ -6774,13 +6778,14 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
divMod->AsOp()->gtOp2 = mul;
}

return mulhi;
*nextNode = mulhi;
return true;
#elif defined(TARGET_ARM)
// Currently there's no GT_MULHI for ARM32
return nullptr;
return false;
#elif defined(TARGET_RISCV64)
NYI_RISCV64("-----unimplemented on RISCV64 yet----");
return nullptr;
return false;
#else
#error Unsupported or unset target architecture
#endif
Expand All @@ -6790,7 +6795,7 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
LIR::Use use;
if (!BlockRange().TryGetUse(node, &use))
{
return nullptr;
return false;
}

// We need to use the dividend node multiple times so its value needs to be
Expand Down Expand Up @@ -6856,7 +6861,8 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
// replace the original divmod node with the new divmod tree
use.ReplaceWith(newDivMod);

return newDivMod->gtNext;
*nextNode = newDivMod->gtNext;
return true;
}
//------------------------------------------------------------------------
// LowerSignedDivOrMod: transform integer GT_DIV/GT_MOD nodes with a power of 2
Expand All @@ -6871,20 +6877,18 @@ GenTree* Lowering::LowerConstIntDivOrMod(GenTree* node)
GenTree* Lowering::LowerSignedDivOrMod(GenTree* node)
{
assert((node->OperGet() == GT_DIV) || (node->OperGet() == GT_MOD));
GenTree* next = node->gtNext;

if (varTypeIsIntegral(node->TypeGet()))
{
// LowerConstIntDivOrMod will return nullptr if it doesn't transform the node.
GenTree* newNode = LowerConstIntDivOrMod(node);
if (newNode != nullptr)
GenTree* nextNode = nullptr;
if (TryLowerConstIntDivOrMod(node, &nextNode))
{
return newNode;
return nextNode;
Copy link
Contributor

Choose a reason for hiding this comment

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

assert(nextNode != nullptr)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The issue is that nextCode can be a nullptr even if the transformation was successful.

But, we could add an assert assert(nextNode == nullptr); if the transformation wasn't successful.

}
}
ContainCheckDivOrMod(node->AsOp());

return next;
return node->gtNext;
}

//------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ class Lowering final : public Phase
bool TryLowerAndNegativeOne(GenTreeOp* node, GenTree** nextNode);
GenTree* LowerBinaryArithmetic(GenTreeOp* binOp);
bool LowerUnsignedDivOrMod(GenTreeOp* divMod);
GenTree* LowerConstIntDivOrMod(GenTree* node);
bool TryLowerConstIntDivOrMod(GenTree* node, GenTree** nextNode);
GenTree* LowerSignedDivOrMod(GenTree* node);
void LowerBlockStore(GenTreeBlk* blkNode);
void LowerBlockStoreCommon(GenTreeBlk* blkNode);
Expand Down
Loading