Commit 1e98dd91 authored by Hao Xu's avatar Hao Xu Committed by V8 LUCI CQ

[compiler] Improve reduction of Word64Comparisons

Add "k <= (x >> n) to (k << n) <= x" reduction to Word64Comparisons.
This can help to reduce the below codes:

  45: Int64Constant[164]
  39: Load[kRepTaggedSigned|kTypeInt32](...)
  40: BitcastTaggedToWordForTagAndSmiBits(39)
  41: TruncateInt64ToInt32(40)
  42: ChangeInt32ToInt64(41)
  43: Word64Sar[ShiftOutZeros](42, 29)
  46: Uint64LessThan(45, 43)

into:

  4530: Int32Constant[328]
  39: Load[kRepTaggedSigned|kTypeInt32](...)
  40: BitcastTaggedToWordForTagAndSmiBits(39)
  41: TruncateInt64ToInt32(40)
  46: Uint32LessThan(4530, 41)

Change-Id: I6ca802c9bb3c941c689ebbcb4ae3072501555266
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3793464
Commit-Queue: Hao A Xu <hao.a.xu@intel.com>
Reviewed-by: 's avatarNico Hartmann <nicohartmann@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82210}
parent ecdde64c
......@@ -1336,18 +1336,25 @@ namespace {
// as "left shifting |value| by |shift| doesn't shift away significant bits".
// Or, equivalently, "left shifting |value| by |shift| doesn't have signed
// overflow".
bool CanRevertLeftShiftWithRightShift(int32_t value, int32_t shift) {
if (shift < 0 || shift >= 32) {
template <typename T>
bool CanRevertLeftShiftWithRightShift(T value, T shift) {
using unsigned_T = typename std::make_unsigned<T>::type;
if (shift < 0 || shift >= std::numeric_limits<T>::digits + 1) {
// This shift would be UB in C++
return false;
}
if (static_cast<int32_t>(static_cast<uint32_t>(value) << shift) >> shift !=
static_cast<int32_t>(value)) {
if (static_cast<T>(static_cast<unsigned_T>(value) << shift) >> shift !=
static_cast<T>(value)) {
return false;
}
return true;
}
bool CanTruncate(int64_t value) {
return value >= std::numeric_limits<int32_t>::min() &&
value <= std::numeric_limits<int32_t>::max();
}
} // namespace
Reduction MachineOperatorReducer::ReduceWord32Comparisons(Node* node) {
......@@ -1377,7 +1384,7 @@ Reduction MachineOperatorReducer::ReduceWord32Comparisons(Node* node) {
Int32BinopMatcher mleft(m.left().node());
if (mleft.right().HasResolvedValue()) {
auto shift = mleft.right().ResolvedValue();
if (CanRevertLeftShiftWithRightShift(right, shift)) {
if (CanRevertLeftShiftWithRightShift<int32_t>(right, shift)) {
node->ReplaceInput(0, mleft.left().node());
node->ReplaceInput(1, Int32Constant(right << shift));
return Changed(node);
......@@ -1393,7 +1400,7 @@ Reduction MachineOperatorReducer::ReduceWord32Comparisons(Node* node) {
Int32BinopMatcher mright(m.right().node());
if (mright.right().HasResolvedValue()) {
auto shift = mright.right().ResolvedValue();
if (CanRevertLeftShiftWithRightShift(left, shift)) {
if (CanRevertLeftShiftWithRightShift<int32_t>(left, shift)) {
node->ReplaceInput(0, Int32Constant(left << shift));
node->ReplaceInput(1, mright.left().node());
return Changed(node);
......@@ -1453,6 +1460,62 @@ Reduction MachineOperatorReducer::ReduceWord64Comparisons(Node* node) {
}
}
// Simplifying (x >> n) <= k into x <= (k << n), with "k << n" being
// computed here at compile time.
if (m.right().HasResolvedValue() &&
m.left().op() == machine()->Word64SarShiftOutZeros() &&
m.left().node()->UseCount() == 1) {
Int64BinopMatcher mleft(m.left().node());
int64_t right = m.right().ResolvedValue();
if (mleft.right().HasResolvedValue()) {
auto shift = mleft.right().ResolvedValue();
if (CanRevertLeftShiftWithRightShift<int64_t>(right, shift)) {
sign_extended = mleft.left().IsChangeInt32ToInt64();
int64_t value = right << shift;
// Reducing to 32-bit comparison when possible.
if ((sign_extended || mleft.left().IsChangeUint32ToUint64()) &&
CanTruncate(value)) {
NodeProperties::ChangeOp(
node, Map64To32Comparison(node->op(), sign_extended));
node->ReplaceInput(0, mleft.left().node()->InputAt(0));
node->ReplaceInput(1, Int32Constant(static_cast<int32_t>(value)));
return Changed(node).FollowedBy(Reduce(node));
}
node->ReplaceInput(0, mleft.left().node());
node->ReplaceInput(1, Int64Constant(value));
return Changed(node);
}
}
}
// Simplifying k <= (x >> n) into (k << n) <= x, with "k << n" being
// computed here at compile time.
if (m.left().HasResolvedValue() &&
m.right().op() == machine()->Word64SarShiftOutZeros() &&
m.right().node()->UseCount() == 1) {
int64_t left = m.left().ResolvedValue();
Int64BinopMatcher mright(m.right().node());
if (mright.right().HasResolvedValue()) {
auto shift = mright.right().ResolvedValue();
if (CanRevertLeftShiftWithRightShift<int64_t>(left, shift)) {
sign_extended = mright.left().IsChangeInt32ToInt64();
int64_t value = left << shift;
// Reducing to 32-bit comparison when possible.
if ((sign_extended || mright.left().IsChangeUint32ToUint64()) &&
CanTruncate(value)) {
NodeProperties::ChangeOp(
node, Map64To32Comparison(node->op(), sign_extended));
node->ReplaceInput(0, Int32Constant(static_cast<int32_t>(value)));
node->ReplaceInput(1, mright.left().node()->InputAt(0));
return Changed(node).FollowedBy(Reduce(node));
}
node->ReplaceInput(0, Int64Constant(value));
node->ReplaceInput(1, mright.left().node());
return Changed(node);
}
}
}
return NoChange();
}
......@@ -2371,7 +2434,7 @@ MachineOperatorReducer::ReduceWord32EqualForConstantRhs(Node* lhs,
typename WordNAdapter::UintNBinopMatcher mshift(lhs);
if (mshift.right().HasResolvedValue()) {
int32_t shift = static_cast<int32_t>(mshift.right().ResolvedValue());
if (CanRevertLeftShiftWithRightShift(rhs, shift)) {
if (CanRevertLeftShiftWithRightShift<int32_t>(rhs, shift)) {
return std::make_pair(mshift.left().node(), rhs << shift);
}
}
......
......@@ -2212,6 +2212,26 @@ TEST_F(MachineOperatorReducerTest, Uint64LessThanWithWord64SarShiftOutZeros) {
}
}
TEST_F(MachineOperatorReducerTest, Uint64LessThanWithUint32Reduction) {
Node* const p = Parameter(0);
TRACED_FORRANGE(int64_t, shift, 1, 3) {
TRACED_FORRANGE(int64_t, rhs, 1, 3) {
Node* const node = graph()->NewNode(
machine()->Uint64LessThan(),
graph()->NewNode(
machine()->Word64SarShiftOutZeros(),
graph()->NewNode(machine()->ChangeUint32ToUint64(), p),
Int64Constant(shift)),
Int64Constant(rhs));
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsUint32LessThan(
p, IsInt32Constant(static_cast<int32_t>(rhs << shift))));
}
}
}
// -----------------------------------------------------------------------------
// Int64LessThan
......@@ -2238,6 +2258,25 @@ TEST_F(MachineOperatorReducerTest, Int64LessThanWithWord64SarShiftOutZeros) {
}
}
TEST_F(MachineOperatorReducerTest, Int64LessThanWithInt32Reduction) {
Node* const p = Parameter(0);
TRACED_FORRANGE(int64_t, shift, 1, 3) {
TRACED_FORRANGE(int64_t, rhs, 1, 3) {
Node* const node = graph()->NewNode(
machine()->Int64LessThan(),
graph()->NewNode(machine()->Word64SarShiftOutZeros(),
graph()->NewNode(machine()->ChangeInt32ToInt64(), p),
Int64Constant(shift)),
Int64Constant(rhs));
Reduction r = Reduce(node);
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(),
IsInt32LessThan(
p, IsInt32Constant(static_cast<int32_t>(rhs << shift))));
}
}
}
// -----------------------------------------------------------------------------
// Float64Mul
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment