5#ifndef V8_COMPILER_TURBOSHAFT_MACHINE_OPTIMIZATION_REDUCER_H_
6#define V8_COMPILER_TURBOSHAFT_MACHINE_OPTIMIZATION_REDUCER_H_
43#if V8_ENABLE_WEBASSEMBLY
117 graph.Get(left_and->left())
126 }
else if (
const ChangeOp* truncate =
129 truncate->input<
Word64>());
137 if (source != other.source ||
141 uint32_t overlapping_bits =
mask & other.mask;
146 (other.masked_value & overlapping_bits)) {
155 template <
typename WordType>
165 if (
int shift_amount;
167 shift_amount >= 0 && shift_amount < 32) {
168 uint32_t
mask = 1 << shift_amount;
184#if defined(__clang__)
203 return Next::ReduceChange(input,
kind, assumption, from, to);
210 from.IsWord() &&
matcher_.MatchIntegralWordConstant(
214 case multi(Kind::kSignExtend, Rep::Word32(), Rep::Word64()):
215 return __ Word64Constant(int64_t{
static_cast<int32_t
>(
value)});
216 case multi(Kind::kZeroExtend, Rep::Word32(), Rep::Word64()):
217 case multi(Kind::kBitcast, Rep::Word32(), Rep::Word64()):
218 return __ Word64Constant(uint64_t{
static_cast<uint32_t
>(
value)});
219 case multi(Kind::kBitcast, Rep::Word32(), Rep::Float32()):
220 return __ Float32Constant(
221 i::Float32::FromBits(
static_cast<uint32_t
>(value)));
222 case multi(Kind::kBitcast, Rep::Word64(), Rep::Float64()):
223 return __ Float64Constant(i::Float64::FromBits(value));
224 case multi(Kind::kSignedToFloat, Rep::Word32(), Rep::Float64()):
225 return __ Float64Constant(
226 static_cast<double>(
static_cast<int32_t
>(value)));
227 case multi(Kind::kSignedToFloat, Rep::Word64(), Rep::Float64()):
228 return __ Float64Constant(
229 static_cast<double>(
static_cast<int64_t
>(value)));
230 case multi(Kind::kUnsignedToFloat, Rep::Word32(), Rep::Float64()):
231 return __ Float64Constant(
232 static_cast<double>(
static_cast<uint32_t
>(value)));
233 case multi(Kind::kTruncate, Rep::Word64(), Rep::Word32()):
234 return __ Word32Constant(
static_cast<uint32_t
>(value));
240 matcher_.MatchFloat32Constant(input, &value)) {
241 if (
kind == Kind::kFloatConversion &&
243 return __ Float64Constant(value.get_scalar());
246 return __ Word32Constant(value.get_bits());
250 matcher_.MatchFloat64Constant(input, &value)) {
251 if (
kind == Kind::kFloatConversion &&
258 if (
kind == Kind::kSignedFloatTruncateOverflowToMin) {
259 double truncated = std::trunc(value.get_scalar());
261 int64_t
result = std::numeric_limits<int64_t>::min();
262 if (truncated >= std::numeric_limits<int64_t>::min() &&
264 result =
static_cast<int64_t
>(truncated);
269 int32_t
result = std::numeric_limits<int32_t>::min();
270 if (truncated >= std::numeric_limits<int32_t>::min() &&
271 truncated <= std::numeric_limits<int32_t>::max()) {
272 result =
static_cast<int32_t
>(truncated);
277 if (
kind == Kind::kJSFloatTruncate &&
281 if (
kind == Kind::kExtractHighHalf) {
283 return __ Word32Constant(
static_cast<uint32_t
>(value.get_bits() >> 32));
285 if (
kind == Kind::kExtractLowHalf) {
287 return __ Word32Constant(
static_cast<uint32_t
>(value.get_bits()));
291 matcher_.MatchFloat32Constant(input, &value)) {
292 if (
kind == Kind::kFloatConversion &&
294 return __ Float64Constant(value);
300 if (change_op->from == to && change_op->to == from &&
302 return change_op->input();
305 return Next::ReduceChange(input,
kind, assumption, from, to);
311 return Next::ReduceBitcastWord32PairToFloat64(hi_word32, lo_word32);
314 if (
matcher_.MatchIntegralWord32Constant(hi_word32, &
hi) &&
315 matcher_.MatchIntegralWord32Constant(lo_word32, &
lo)) {
316 return __ Float64Constant(
319 return Next::ReduceBitcastWord32PairToFloat64(hi_word32, lo_word32);
326 return Next::ReduceTaggedBitcast(input, from, to,
kind);
332 if (
all_of(input_bitcast->to, from) ==
335 return input_bitcast->input();
340 input_bitcast && to.IsWord() &&
343 if (input_bitcast->from == to)
return input_bitcast->input();
346 return __ BitcastWord32ToWord64(input_bitcast->input());
350 return __ TruncateWord64ToWord32(input_bitcast->input());
358 return __ Word64Constant(cst->integral());
361 return __ Word32Constant(
static_cast<uint32_t
>(cst->integral()));
370 return __ SmiConstant(
377 return __ Word32Constant(
static_cast<uint32_t
>(cst->smi().ptr()));
379 return __ Word64Constant(
static_cast<uint64_t
>(cst->smi().ptr()));
383 return Next::ReduceTaggedBitcast(input, from, to,
kind);
389 return Next::ReduceFloatUnary(input,
kind, rep);
392 matcher_.MatchFloat32Constant(input, &f32_k)) {
394 return __ Float32Constant(std::numeric_limits<float>::quiet_NaN());
398 return __ Float32Constant(std::abs(f32_k));
400 return __ Float32Constant(-f32_k);
402 DCHECK(!std::isnan(f32_k));
403 return __ Float32Constant(f32_k);
405 return __ Float32Constant(std::floor(f32_k));
407 return __ Float32Constant(std::ceil(f32_k));
409 return __ Float32Constant(std::trunc(f32_k));
413 return __ Float32Constant(std::nearbyint(f32_k));
417 return __ Float32Constant(std::sqrt(f32_k));
456 matcher_.MatchFloat64Constant(input, &f64_k)) {
458 return __ Float64Constant(std::numeric_limits<double>::quiet_NaN());
462 return __ Float64Constant(std::abs(f64_k));
464 return __ Float64Constant(-f64_k);
466 DCHECK(!std::isnan(f64_k));
467 return __ Float64Constant(f64_k);
469 return __ Float64Constant(std::floor(f64_k));
471 return __ Float64Constant(std::ceil(f64_k));
473 return __ Float64Constant(std::trunc(f64_k));
477 return __ Float64Constant(std::nearbyint(f64_k));
481 return __ Float64Constant(std::sqrt(f64_k));
520 return Next::ReduceFloatUnary(input,
kind, rep);
526 return Next::ReduceWordUnary(input,
kind, rep);
532 matcher_.MatchIntegralWord32Constant(input, &w32_k)) {
543 return __ Word32Constant(int32_t{
static_cast<int8_t
>(w32_k)});
545 return __ Word32Constant(int32_t{
static_cast<int16_t
>(w32_k)});
547 }
else if (uint64_t w64_k;
549 matcher_.MatchIntegralWord64Constant(input, &w64_k)) {
554 return __ Word64Constant(
557 return __ Word64Constant(
560 return __ Word64Constant(
563 return __ Word64Constant(int64_t{
static_cast<int8_t
>(w64_k)});
565 return __ Word64Constant(int64_t{
static_cast<int16_t
>(w64_k)});
568 return Next::ReduceWordUnary(input,
kind, rep);
575 return Next::ReduceFloatBinop(lhs, rhs,
kind, rep);
583 return ReduceFloatBinop(rhs, lhs,
kind, rep);
588 matcher_.MatchFloat32Constant(lhs, &k1) &&
589 matcher_.MatchFloat32Constant(rhs, &k2)) {
592 return __ Float32Constant(k1 + k2);
594 return __ Float32Constant(k1 * k2);
596 return __ Float32Constant(k1 - k2);
598 return __ Float32Constant(
JSMin(k1, k2));
600 return __ Float32Constant(
JSMax(k1, k2));
602 return __ Float32Constant(k1 / k2);
612 matcher_.MatchFloat64Constant(lhs, &k1) &&
613 matcher_.MatchFloat64Constant(rhs, &k2)) {
616 return __ Float64Constant(k1 + k2);
618 return __ Float64Constant(k1 * k2);
620 return __ Float64Constant(k1 - k2);
622 return __ Float64Constant(
JSMin(k1, k2));
624 return __ Float64Constant(
JSMax(k1, k2));
626 return __ Float64Constant(k1 / k2);
628 return __ Float64Constant(
Modulo(k1, k2));
641 return __ FloatConstant(std::numeric_limits<double>::quiet_NaN(), rep);
645 if (
kind == Kind::kMul) {
651 if (
matcher_.MatchFloat(rhs, 2.0)) {
652 return __ FloatAdd(lhs, lhs, rep);
656 return __ FloatNegate(lhs, rep);
660 if (
kind == Kind::kDiv) {
667 return __ FloatNegate(lhs, rep);
675 matcher_.MatchFloat32Constant(rhs, &k) && std::isnormal(k) &&
676 k != 0 && std::isfinite(k) &&
678 return __ FloatMul(lhs,
__ FloatConstant(1.0 / k, rep), rep);
683 matcher_.MatchFloat64Constant(rhs, &k) && std::isnormal(k) &&
684 k != 0 && std::isfinite(k) &&
686 return __ FloatMul(lhs,
__ FloatConstant(1.0 / k, rep), rep);
691 if (
kind == Kind::kMod) {
693 if (
matcher_.MatchFloat(rhs, 0.0)) {
694 return __ FloatConstant(std::numeric_limits<double>::quiet_NaN(),
699 if (
kind == Kind::kSub) {
706 if (
kind == Kind::kPower) {
709 return __ FloatConstant(1.0, rep);
711 if (
matcher_.MatchFloat(rhs, 2.0)) {
713 return __ FloatMul(lhs, lhs, rep);
715 if (
matcher_.MatchFloat(rhs, 0.5)) {
725 __ FloatSqrt(
__ FloatAdd(lhs,
__ FloatConstant(0, rep), rep),
739 matcher_.MatchFloatRoundDown(rhs, &a, rep) &&
740 matcher_.MatchFloatSub(a, &b, &c, rep) &&
742 return __ FloatRoundUp(c, rep);
745 return __ FloatNegate(rhs, rep);
748 return Next::ReduceFloatBinop(lhs, rhs,
kind, rep);
754 return Next::ReduceWordBinop(left, right,
kind, rep);
771 return ReduceWordBinop(right, left,
kind, rep);
774 if (uint64_t k1, k2;
matcher_.MatchIntegralWordConstant(left, rep, &k1) &&
775 matcher_.MatchIntegralWordConstant(right, rep, &k2)) {
778 return __ WordConstant(k1 + k2, rep);
780 return __ WordConstant(k1 * k2, rep);
781 case Kind::kBitwiseAnd:
782 return __ WordConstant(k1 & k2, rep);
783 case Kind::kBitwiseOr:
784 return __ WordConstant(k1 | k2, rep);
785 case Kind::kBitwiseXor:
786 return __ WordConstant(k1 ^ k2, rep);
788 return __ WordConstant(k1 - k2, rep);
789 case Kind::kSignedMulOverflownBits:
790 return __ WordConstant(
792 static_cast<int64_t
>(k2))
794 static_cast<int32_t
>(k2)),
796 case Kind::kUnsignedMulOverflownBits:
797 return __ WordConstant(
800 static_cast<uint32_t
>(k2)),
802 case Kind::kSignedDiv:
803 return __ WordConstant(
806 static_cast<int32_t
>(k2)),
808 case Kind::kUnsignedDiv:
809 return __ WordConstant(
812 static_cast<uint32_t
>(k2)),
814 case Kind::kSignedMod:
815 return __ WordConstant(
818 static_cast<int32_t
>(k2)),
820 case Kind::kUnsignedMod:
821 return __ WordConstant(
824 static_cast<uint32_t
>(k2)),
835 if (
auto combined_bitfield =
836 left_bitfield->TryCombine(*right_bitfield)) {
837 V<Word> source = combined_bitfield->source;
838 if (combined_bitfield->truncate_from_64_bit) {
842 combined_bitfield->mask),
843 combined_bitfield->masked_value);
849 if (uint64_t right_value;
850 matcher_.MatchIntegralWordConstant(right, rep, &right_value)) {
853 int64_t right_value_signed =
854 is_64 ?
static_cast<int64_t
>(right_value)
855 : int64_t{
static_cast<int32_t
>(right_value)};
868 if (
matcher_.Get(left).saturated_use_count.IsZero()) {
869 return ReduceWordBinop(a, ReduceWordBinop(k1, k2,
kind, rep),
kind,
876 return ReduceWordBinop(left,
__ WordConstant(-right_value, rep),
880 if (right_value == 0) {
884 case Kind::kBitwiseXor:
886 if (right_value == 0) {
890 if (right_value == 1 &&
IsBit(left)) {
897 if (right_value_signed == -1 &&
898 matcher_.MatchBitwiseAnd(left, &
x, &
y, rep) &&
899 matcher_.MatchIntegralWordConstant(
y, rep, &k) && k == -1) {
904 case Kind::kBitwiseOr:
906 if (right_value == 0) {
910 if (right_value_signed == -1) {
918 uint64_t k2 = right_value;
919 if (
matcher_.MatchBitwiseAnd(left, &
x, &
y, rep) &&
920 matcher_.MatchIntegralWordConstant(
y, rep, &k1) &&
921 (k1 | k2) == rep.MaxUnsignedValue()) {
922 return __ WordBitwiseOr(
x, right, rep);
928 if (right_value == 0) {
929 return __ WordConstant(0, rep);
932 if (right_value == 1) {
936 if (right_value_signed == -1) {
937 return __ WordSub(
__ WordConstant(0, rep), left, rep);
945 case Kind::kBitwiseAnd:
947 if (right_value_signed == -1) {
951 if (right_value == 0) {
955 if (right_value == 1) {
957 V<Word> left_ignore_extensions =
962 matcher_.MatchWordAdd(left_ignore_extensions, &a, &b,
965 return __ WordConstant(0, rep);
969 if (
IsBit(left_ignore_extensions)) {
976 return __ WordConstant(1, rep);
978 return __ WordConstant(0, rep);
989 uint64_t
mask = right_value;
996 if (
matcher_.MatchConstantLeftShift(left, &
x, rep, &
L) &&
1002 if (
matcher_.MatchWordAdd(left, &
x, &
y, rep)) {
1007 if (
matcher_.MatchIntegralWordConstant(
y, rep, &
L) &&
1009 return __ WordAdd(
__ WordBitwiseAnd(
x, right, rep),
1010 __ WordConstant(
L, rep), rep);
1016 if (
matcher_.MatchWordMul(
x, &x1, &x2, rep) &&
1017 matcher_.MatchIntegralWordConstant(x2, rep, &
L) &&
1019 return __ WordAdd(
x,
__ WordBitwiseAnd(
y, right, rep), rep);
1024 if (
matcher_.MatchWordMul(
y, &y1, &y2, rep) &&
1025 matcher_.MatchIntegralWordConstant(y2, rep, &
L) &&
1027 return __ WordAdd(
__ WordBitwiseAnd(
x, right, rep),
y, rep);
1033 if (
matcher_.MatchConstantLeftShift(
x, &x1, rep, &K2) &&
1035 return __ WordAdd(
x,
__ WordBitwiseAnd(
y, right, rep), rep);
1040 if (
matcher_.MatchConstantLeftShift(
y, &y1, rep, &K2) &&
1042 return __ WordAdd(
__ WordBitwiseAnd(
x, right, rep),
y, rep);
1044 }
else if (
matcher_.MatchWordMul(left, &
x, &
y, rep)) {
1047 if (
matcher_.MatchIntegralWordConstant(
y, rep, &
L) &&
1062 if (right_value_signed ==
any_of(0, 1, -1)) {
1063 return __ WordConstant(0, rep);
1065 if (right_value_signed != rep.MinSignedValue()) {
1066 right_value_signed =
Abs(right_value_signed);
1077 uint32_t bits = rep.bit_width();
1080 __ ShiftRightArithmetic(left, bits - 1, rep), bits - n, rep);
1082 __ WordBitwiseAnd(
__ WordAdd(left,
m, rep),
1083 __ WordConstant(right_value_signed - 1, rep),
1090 left,
__ WordMul(
__ IntDiv(left, right, rep), right, rep), rep);
1094 if (right_value == 0 || right_value == 1) {
1095 return __ WordConstant(0, rep);
1099 return __ WordBitwiseAnd(
1100 left,
__ WordConstant(right_value - 1, rep), rep);
1105 left,
__ WordMul(right,
__ UintDiv(left, right, rep), rep), rep);
1112 if (
kind == Kind::kAdd) {
1115 if (
matcher_.MatchWordSub(left, &zero, &
x, rep) &&
1118 return __ WordSub(
y,
x, rep);
1121 if (
matcher_.MatchWordSub(right, &zero, &
y, rep) &&
1124 return __ WordSub(
x,
y, rep);
1131 kind ==
any_of(Kind::kSignedDiv, Kind::kUnsignedDiv, Kind::kUnsignedMod,
1132 Kind::kSignedMod)) {
1133 return __ WordConstant(0, rep);
1136 if (left == right) {
1151 return __ WordConstant(0, rep);
1157 return __ ZeroExtendWord32ToRep(
result, rep);
1171 return Next::ReduceWordBinop(left, right,
kind, rep);
1175 constexpr int kMaxDepth = 2;
1176 if (depth == kMaxDepth)
return false;
1178 if (
matcher_.MatchHeapConstant(idx))
return true;
1185 return TryMatchHeapObject(input, depth + 1);
1212 if (!high)
return {};
1214 if (!low)
return {};
1216 if (low->kind == ShiftOp::Kind::kShiftLeft) {
1217 std::swap(low, high);
1219 if (high->
kind != ShiftOp::Kind::kShiftLeft ||
1220 low->kind != ShiftOp::Kind::kShiftRightLogical) {
1224 if (low->left() !=
x)
return {};
1226 if (uint64_t k1, k2;
1227 matcher_.MatchIntegralWordConstant(high->
right(), rep, &k1) &&
1228 matcher_.MatchIntegralWordConstant(low->right(), rep, &k2) &&
1229 k1 + k2 == rep.
bit_width() && k1 >= 0 && k2 >= 0) {
1230 if (k1 == 0 || k2 == 0) {
1232 return __ WordConstant(0, rep);
1238 return __ RotateRight(
x, low->right(), rep);
1250 matcher_.MatchIntegralWordConstant(a, rep, &k) && b == low->right() &&
1252 return __ RotateRight(
x, b, rep);
1253 }
else if (
matcher_.MatchWordSub(low->right(), &a, &b, rep) &&
1254 matcher_.MatchIntegralWordConstant(a, rep, &k) &&
1256 return __ RotateRight(
x, low->right(), rep);
1266 return Next::ReduceOverflowCheckedBinop(left, right,
kind, rep);
1271 return ReduceOverflowCheckedBinop(right, left,
kind, rep);
1279 if (int32_t k1, k2;
matcher_.MatchIntegralWord32Constant(left, &k1) &&
1280 matcher_.MatchIntegralWord32Constant(right, &k2)) {
1294 return __ Tuple(
__ Word32Constant(res),
__ Word32Constant(overflow));
1298 if (int64_t k1, k2;
matcher_.MatchIntegralWord64Constant(left, &k1) &&
1299 matcher_.MatchIntegralWord64Constant(right, &k2)) {
1313 return __ Tuple(
__ Word64Constant(res),
__ Word32Constant(overflow));
1319 if (
kind ==
any_of(Kind::kSignedAdd, Kind::kSignedSub) &&
1321 return __ Tuple(left,
__ Word32Constant(0));
1324 if (
kind == Kind::kSignedMul) {
1325 if (int64_t k;
matcher_.MatchIntegralWordConstant(right, rep, &k)) {
1328 return __ Tuple(
__ WordConstant(0, rep),
__ Word32Constant(
false));
1332 return __ Tuple(left,
__ Word32Constant(
false));
1336 return __ IntSubCheckOverflow(
__ WordConstant(0, rep), left, rep);
1340 return __ IntAddCheckOverflow(left, left, rep);
1347 if (
kind == Kind::kSignedAdd && left == right) {
1356 return Next::ReduceOverflowCheckedBinop(left, right,
kind, rep);
1363 return Next::ReduceComparison(left, right,
kind, rep);
1373 if (left == right &&
1377 Kind::kUnsignedLessThanOrEqual)) {
1381 case Kind::kUnsignedLessThanOrEqual:
1382 case Kind::kSignedLessThanOrEqual:
1383 return __ Word32Constant(1);
1384 case Kind::kUnsignedLessThan:
1385 case Kind::kSignedLessThan:
1386 return __ Word32Constant(0);
1391 switch (rep.value()) {
1395 any_of(Kind::kSignedLessThan, Kind::kSignedLessThanOrEqual)) {
1396 if (int64_t k1, k2;
matcher_.MatchIntegralWordConstant(
1398 matcher_.MatchIntegralWordConstant(
1402 return __ Word32Constant(k1 < k2);
1404 return __ Word32Constant(k1 <= k2);
1412 if (uint64_t k1, k2;
matcher_.MatchIntegralWordConstant(
1414 matcher_.MatchIntegralWordConstant(
1418 return __ Word32Constant(k1 < k2);
1420 return __ Word32Constant(k1 <= k2);
1431 if (
float k1, k2;
matcher_.MatchFloat32Constant(left, &k1) &&
1432 matcher_.MatchFloat32Constant(right, &k2)) {
1435 return __ Word32Constant(k1 < k2);
1437 return __ Word32Constant(k1 <= k2);
1447 if (
double k1, k2;
matcher_.MatchFloat64Constant(left, &k1) &&
1448 matcher_.MatchFloat64Constant(right, &k2)) {
1451 return __ Word32Constant(k1 < k2);
1453 return __ Word32Constant(k1 <= k2);
1476 if (
kind == Kind::kUnsignedLessThanOrEqual) {
1479 matcher_.MatchIntegralWordConstant(left, rep_w, &k) && k == 0) {
1480 return __ Word32Constant(1);
1483 if (uint64_t k;
matcher_.MatchIntegralWordConstant(right, rep_w, &k) &&
1484 k == rep.MaxUnsignedValue()) {
1485 return __ Word32Constant(1);
1489 matcher_.MatchIntegralWordConstant(right, rep_w, &k) && k == 0) {
1490 return __ Equal(left,
__ WordConstant(0, rep_w), rep_w);
1493 if (
kind == Kind::kUnsignedLessThan) {
1496 matcher_.MatchIntegralWordConstant(right, rep_w, &k) && k == 0) {
1497 return __ Word32Constant(0);
1500 if (uint64_t k;
matcher_.MatchIntegralWordConstant(left, rep_w, &k) &&
1501 k == rep.MaxUnsignedValue()) {
1502 return __ Word32Constant(0);
1509 if (
matcher_.MatchConstantShiftRightArithmeticShiftOutZeros(
1510 left, &
x, rep_w, &k1) &&
1511 matcher_.MatchConstantShiftRightArithmeticShiftOutZeros(
1512 right, &
y, rep_w, &k2) &&
1524 if (
matcher_.MatchConstantShiftRightArithmeticShiftOutZeros(
1525 left, &
x, rep_w, &k1) &&
1526 matcher_.MatchIntegralWordConstant(right, rep_w, &k2) &&
1528 if (
matcher_.Get(left).saturated_use_count.IsZero()) {
1543 if (
__ WillGVNOp(*cmp)) {
1551 if (
matcher_.MatchConstantShiftRightArithmeticShiftOutZeros(
1552 right, &
x, rep_w, &k1) &&
1553 matcher_.MatchIntegralWordConstant(left, rep_w, &k2) &&
1555 if (
matcher_.Get(right).saturated_use_count.IsZero()) {
1570 if (
__ WillGVNOp(*cmp)) {
1578 std::optional<bool> left_sign_extended;
1579 std::optional<bool> right_sign_extended;
1582 if (left_sign_extended !=
true && right_sign_extended !=
true) {
1587 case Kind::kSignedLessThan:
1588 case Kind::kUnsignedLessThan:
1589 return is_signed ? Kind::kSignedLessThan
1590 : Kind::kUnsignedLessThan;
1591 case Kind::kSignedLessThanOrEqual:
1592 case Kind::kUnsignedLessThanOrEqual:
1593 return is_signed ? Kind::kSignedLessThanOrEqual
1594 : Kind::kUnsignedLessThanOrEqual;
1603 }
else if (left_sign_extended !=
false &&
1604 right_sign_extended !=
false) {
1615 return Next::ReduceComparison(left, right,
kind, rep);
1621 return Next::ReduceShift(left, right,
kind, rep);
1628 using Kind = ShiftOp::Kind;
1629 uint64_t c_unsigned;
1631 if (
matcher_.MatchIntegralWordConstant(left, rep, &c_unsigned, &c_signed)) {
1632 if (uint32_t amount;
1633 matcher_.MatchIntegralWord32Constant(right, &amount)) {
1634 amount = amount & (rep.bit_width() - 1);
1636 case Kind::kShiftRightArithmeticShiftOutZeros:
1644 case Kind::kShiftRightArithmetic:
1645 switch (rep.value()) {
1647 return __ Word32Constant(
static_cast<int32_t
>(c_signed) >>
1650 return __ Word64Constant(c_signed >> amount);
1652 case Kind::kShiftRightLogical:
1653 switch (rep.value()) {
1655 return __ Word32Constant(
static_cast<uint32_t
>(c_unsigned) >>
1658 return __ Word64Constant(c_unsigned >> amount);
1660 case Kind::kShiftLeft:
1661 return __ WordConstant(c_unsigned << amount, rep);
1662 case Kind::kRotateRight:
1663 switch (rep.value()) {
1666 static_cast<uint32_t
>(c_unsigned), amount));
1668 return __ Word64Constant(
1671 case Kind::kRotateLeft:
1672 switch (rep.value()) {
1675 static_cast<uint32_t
>(c_unsigned), amount));
1677 return __ Word64Constant(
1683 if (int32_t amount;
matcher_.MatchIntegralWord32Constant(right, &amount) &&
1684 0 <= amount && amount < rep.bit_width()) {
1688 if (
kind == Kind::kShiftLeft) {
1698 left, &
x, Kind::kShiftRightArithmeticShiftOutZeros, rep, &k)) {
1703 return __ ShiftRightArithmeticShiftOutZeros(
1704 x,
__ Word32Constant(k - l), rep);
1706 return __ ShiftLeft(
x,
__ Word32Constant(l - k), rep);
1711 if (
matcher_.MatchConstantRightShift(left, &
x, rep, &k) &&
1713 return __ WordBitwiseAnd(
1714 x,
__ WordConstant(rep.MaxUnsignedValue() << k, rep), rep);
1717 if (
kind ==
any_of(Kind::kShiftRightArithmetic,
1718 Kind::kShiftRightArithmeticShiftOutZeros)) {
1720 int left_shift_amount;
1722 if (
matcher_.MatchConstantShift(left, &
x, ShiftOp::Kind::kShiftLeft,
1723 rep, &left_shift_amount) &&
1724 amount == left_shift_amount) {
1726 if (amount == rep.bit_width() - 1 &&
IsBit(
x)) {
1727 return __ WordSub(
__ WordConstant(0, rep),
x, rep);
1730 if (amount <= rep.bit_width() - 8 &&
IsInt8(
x)) {
1734 if (amount <= rep.bit_width() - 16 &&
IsInt16(
x)) {
1740 SupportedOperations::word32_shift_is_safe()) {
1745#if defined(__clang__)
1748 if (uint32_t b_value;
1749 matcher_.MatchIntegralWord32Constant(b, &b_value) &&
1756 return Next::ReduceShift(left, right,
kind, rep);
1762 return Next::ReduceBranch(
condition, if_true, if_false, hint);
1768 __ Goto(*decision ? if_true : if_false);
1774 bool negated =
false;
1775 if (std::optional<OpIndex> new_condition =
1778 std::swap(if_true, if_false);
1782 return __ ReduceBranch(new_condition.value(), if_true, if_false, hint);
1792 return Next::ReduceDeoptimizeIf(
condition, frame_state, negated,
1796 if (*decision != negated) {
1797 __ Deoptimize(frame_state, parameters);
1802 if (std::optional<
V<Word32>> new_condition =
1804 return __ ReduceDeoptimizeIf(new_condition.value(), frame_state, negated,
1807 return Next::ReduceDeoptimizeIf(
condition, frame_state, negated,
1812#if V8_ENABLE_WEBASSEMBLY
1814 bool negated, TrapId trap_id) {
1816 return Next::ReduceTrapIf(
condition, frame_state, negated, trap_id);
1820 if (*decision != negated) {
1821 Next::ReduceTrapIf(
condition, frame_state, negated, trap_id);
1827 if (std::optional<
V<Word32>> new_condition =
1829 return __ ReduceTrapIf(new_condition.value(), frame_state, negated,
1841 return Next::ReduceSelect(cond, vtrue, vfalse, rep, hint, implem);
1847 return *decision ? vtrue : vfalse;
1855 return Next::ReduceStaticAssert(
condition, source);
1872 return Next::ReduceSwitch(input, cases,
default_case, default_hint);
1875 if (int32_t value;
matcher_.MatchIntegralWord32Constant(input, &value)) {
1877 if (if_value.value == value) {
1878 __ Goto(if_value.destination);
1891 uint8_t element_scale,
1892 bool maybe_initializing_or_transitioning,
1895 return Next::ReduceStore(base_idx, index, value,
kind, stored_rep,
1896 write_barrier,
offset, element_scale,
1897 maybe_initializing_or_transitioning,
1898 maybe_indirect_pointer_tag);
1901#if V8_TARGET_ARCH_32_BIT
1902 if (
kind.is_atomic && stored_rep.SizeInBytes() == 8) {
1909 if (stored_rep.SizeInBytes() <= 4) {
1914 switch (stored_rep) {
1941 base_idx =
base.left();
1942 index =
base.right();
1946 element_scale, maybe_initializing_or_transitioning,
1947 maybe_indirect_pointer_tag);
1951 return Next::ReduceStore(base_idx, index, value,
kind, stored_rep,
1952 write_barrier,
offset, element_scale,
1953 maybe_initializing_or_transitioning,
1954 maybe_indirect_pointer_tag);
1960 uint8_t element_scale) {
1962 return Next::ReduceLoad(base_idx, index,
kind, loaded_rep, result_rep,
1966#if V8_TARGET_ARCH_32_BIT
1967 if (
kind.is_atomic && loaded_rep.SizeInBytes() == 8) {
1977 &element_scale,
kind.tagged_base);
1978 if (!
kind.tagged_base && !index.valid()) {
1980 matcher_.MatchWordAdd(base_idx, &left, &right,
1983 kind.tagged_base)) {
2008 return __ HeapConstant(map->object());
2027 base_idx =
base.left();
2028 index =
base.right();
2035 return Next::ReduceLoad(base_idx, index,
kind, loaded_rep, result_rep,
2039#if V8_ENABLE_WEBASSEMBLY
2040#ifdef V8_TARGET_ARCH_ARM64
2042 Simd128ExtractLaneOp::Kind
kind,
2045 return Next::ReduceSimd128ExtractLane(input,
kind, lane);
2053 const Simd128BinopOp* binop =
matcher_.TryCast<Simd128BinopOp>(input);
2059 switch (binop->kind) {
2062 case Simd128BinopOp::Kind::kI8x16Add:
2063 case Simd128BinopOp::Kind::kI16x8Add:
2064 case Simd128BinopOp::Kind::kI32x4Add:
2065 case Simd128BinopOp::Kind::kF32x4Add:
2066 case Simd128BinopOp::Kind::kI64x2Add:
2067 case Simd128BinopOp::Kind::kF64x2Add:
2072 [
this](
V<Simd128> maybe_shuffle) ->
const Simd128ShuffleOp* {
2073 if (
const Simd128ShuffleOp* shuffle =
2074 matcher_.TryCast<Simd128ShuffleOp>(maybe_shuffle)) {
2075 if (shuffle->kind == Simd128ShuffleOp::Kind::kI8x16) {
2085 Simd128BinopOp::Kind required_binop_kind) ->
const Simd128BinopOp* {
2086 if (
const Simd128BinopOp* binop =
2087 matcher_.TryCast<Simd128BinopOp>(maybe_binop)) {
2088 if (required_binop_kind == binop->kind) {
2110 base::SmallVector<const Simd128ShuffleOp*, 4> shuffles;
2111 base::SmallVector<const Simd128BinopOp*, 4> binops;
2112 binops.push_back(binop);
2113 while (!binops.empty()) {
2114 const Simd128BinopOp* binop = binops.back();
2116 V<Simd128> operands[2] = {binop->left(), binop->right()};
2117 for (
unsigned i = 0;
i < 2; ++
i) {
2119 if (
const Simd128ShuffleOp* shuffle = MatchShuffle(operand)) {
2125 if (shuffle_in != other_operand) {
2128 shuffles.push_back(shuffle);
2129 if (
const Simd128BinopOp* other_binop =
2130 MatchBinop(shuffle_in, binop->kind)) {
2131 binops.push_back(other_binop);
2137 if (shuffles.empty()) {
2142 std::reverse(shuffles.begin(), shuffles.end());
2143 V<Simd128> reduce_input = shuffles.front()->left();
2149 if (shuffles.size() == 4) {
2150 const uint8_t* shuffle1 = shuffles[0]->shuffle;
2151 const uint8_t* shuffle2 = shuffles[1]->shuffle;
2152 const uint8_t* shuffle3 = shuffles[2]->shuffle;
2153 const uint8_t* shuffle4 = shuffles[3]->shuffle;
2155 shuffle1, shuffle2, shuffle3, shuffle4)) {
2157 reduce_input, Simd128ReduceOp::Kind::kI8x16AddReduce);
2158 return __ Simd128ExtractLane(reduce,
kind, 0);
2164 if (shuffles.size() == 3) {
2165 const uint8_t* shuffle1 = shuffles[0]->shuffle;
2166 const uint8_t* shuffle2 = shuffles[1]->shuffle;
2167 const uint8_t* shuffle3 = shuffles[2]->shuffle;
2169 shuffle1, shuffle2, shuffle3)) {
2171 reduce_input, Simd128ReduceOp::Kind::kI16x8AddReduce);
2172 return __ Simd128ExtractLane(reduce,
kind, 0);
2178 if (shuffles.size() == 2) {
2179 const uint8_t* shuffle1 = shuffles[0]->shuffle;
2180 const uint8_t* shuffle2 = shuffles[1]->shuffle;
2184 reduce_input, Simd128ReduceOp::Kind::kI32x4AddReduce);
2185 return __ Simd128ExtractLane(reduce,
kind, 0);
2191 if (shuffles.size() == 2) {
2192 const uint8_t* shuffle1 = shuffles[0]->shuffle;
2193 const uint8_t* shuffle2 = shuffles[1]->shuffle;
2197 reduce_input, Simd128ReduceOp::Kind::kF32x4AddReduce);
2198 return __ Simd128ExtractLane(reduce,
kind, 0);
2205 if (shuffles.size() == 1) {
2206 uint8_t shuffle64x2[2];
2212 ?
__ Simd128Reduce(reduce_input,
2213 Simd128ReduceOp::Kind::kI64x2AddReduce)
2214 :
__ Simd128Reduce(reduce_input,
2215 Simd128ReduceOp::Kind::kF64x2AddReduce);
2216 return __ Simd128ExtractLane(reduce,
kind, 0);
2230 if (left == right && !rep.
IsFloat()) {
2231 return __ Word32Constant(1);
2243 switch (rep.
value()) {
2246 if (uint64_t k1, k2;
matcher_.MatchIntegralWordConstant(
2248 matcher_.MatchIntegralWordConstant(
2250 return __ Word32Constant(k1 == k2);
2255 if (
float k1, k2;
matcher_.MatchFloat32Constant(left, &k1) &&
2256 matcher_.MatchFloat32Constant(right, &k2)) {
2257 return __ Word32Constant(k1 == k2);
2262 if (
double k1, k2;
matcher_.MatchFloat64Constant(left, &k1) &&
2263 matcher_.MatchFloat64Constant(right, &k2)) {
2264 return __ Word32Constant(k1 == k2);
2270 matcher_.MatchHeapConstant(left, &o1) &&
2271 matcher_.MatchHeapConstant(right, &o2)) {
2273 if (IsString(*o1) && IsString(*o2)) {
2276 if (o1.
address() == o2.address())
return __ Word32Constant(1);
2283 return __ Word32Constant(o1.
address() == o2.address());
2304 if (
matcher_.MatchBitwiseAnd(left, &shift, &mask_op, rep_w) &&
2305 matcher_.MatchConstantRightShift(shift, &
x, rep_w,
2307 matcher_.MatchIntegralWordConstant(mask_op, rep_w, &
mask) &&
2308 matcher_.MatchIntegralWordConstant(right, rep_w, &k) &&
2313 x,
__ WordConstant(
mask << shift_amount, rep_w), rep_w),
2314 __ WordConstant(k << shift_amount, rep_w), rep_w);
2324 if (
matcher_.MatchConstantShiftRightArithmeticShiftOutZeros(
2325 left, &
x, rep_w, &k1) &&
2326 matcher_.MatchIntegralWordConstant(right, rep_w, &k2) &&
2328 matcher_.Get(left).saturated_use_count.IsZero()) {
2336 std::optional<bool> left_sign_extended;
2337 std::optional<bool> right_sign_extended;
2340 if (left_sign_extended == right_sign_extended) {
2356 uint8_t element_scale,
bool tagged_base) {
2360 !constant.IsIntegral()) {
2368 if (element_scale > 31)
return false;
2369 if (diff <= (std::numeric_limits<int32_t>::max() >> element_scale) &&
2370 diff >= (std::numeric_limits<int32_t>::min() >> element_scale) &&
2383 const Operation& maybe_constant, uint8_t element_scale) {
2387 !constant.IsIntegral()) {
2405 if (!
matcher_.MatchIntegralWordConstant(
2411 uint64_t{*element_scale})) {
2412 *element_scale += diff;
2423 uint8_t* element_scale,
bool tagged_base) {
2424 while (index.valid()) {
2436 if (shift_op->kind == ShiftOp::Kind::kShiftLeft &&
2438 index = shift_op->left();
2450 *element_scale, tagged_base)) {
2451 index = binary_op->left();
2506 std::optional<bool>* sign_extended =
nullptr) {
2511 if (sign_extended) *sign_extended =
true;
2514 if (sign_extended) *sign_extended =
false;
2519 if (int64_t c;
matcher_.MatchIntegralWord64Constant(value, &c) &&
2520 c >= std::numeric_limits<int32_t>::min()) {
2522 if (sign_extended) *sign_extended =
true;
2524 }
else if (c <= std::numeric_limits<int32_t>::max()) {
2526 if (sign_extended) *sign_extended = {};
2528 }
else if (c <= std::numeric_limits<uint32_t>::max()) {
2529 if (sign_extended) *sign_extended =
false;
2558 return static_cast<uint32_t
>(
value);
2571 uint64_t mask_value;
2572 if (
matcher_.MatchBitwiseAnd(value, &input, &
mask, rep) &&
2573 matcher_.MatchIntegralWordConstant(
mask, rep, &mask_value)) {
2574 if ((mask_value & truncation_mask) == truncation_mask) {
2580 int left_shift_amount;
2581 int right_shift_amount;
2584 ShiftOp::Kind right_shift_kind;
2586 if (
matcher_.MatchConstantShift(value, &left_shift, &right_shift_kind,
2587 &value_rep, &right_shift_amount) &&
2588 ShiftOp::IsRightShift(right_shift_kind) &&
2589 matcher_.MatchConstantShift(left_shift, &left_shift_input,
2590 ShiftOp::Kind::kShiftLeft, value_rep,
2591 &left_shift_amount) &&
2593 truncation_mask) == truncation_mask) {
2594 if (left_shift_amount == right_shift_amount) {
2595 return left_shift_input;
2596 }
else if (left_shift_amount < right_shift_amount) {
2598 __ Word32Constant(right_shift_amount - left_shift_amount);
2599 return __ Shift(left_shift_input, shift_amount, right_shift_kind,
2601 }
else if (left_shift_amount > right_shift_amount) {
2603 __ Word32Constant(left_shift_amount - right_shift_amount);
2604 return __ Shift(left_shift_input, shift_amount,
2605 ShiftOp::Kind::kShiftLeft, value_rep);
2615 return __ WordSub(
__ WordConstant(0, rep), left, rep);
2619 return __ WordConstant(0, rep);
2627 V<Word32> equal_op =
__ Equal(left,
__ WordConstant(right, rep), rep);
2629 return __ ChangeUint32ToUint64(equal_op);
2637 return __ WordSub(
__ WordConstant(0, rep),
2646 quotient =
__ ShiftRightArithmetic(quotient, rep.
bit_width() - 1, rep);
2648 quotient =
__ ShiftRightLogical(quotient, rep.
bit_width() - shift, rep);
2649 quotient =
__ WordAdd(quotient, left, rep);
2650 quotient =
__ ShiftRightArithmetic(quotient, shift, rep);
2657 base::MagicNumbersForDivision<
decltype(right)> magic =
2659 V<Word> quotient =
__ IntMulOverflownBits(
2660 left,
__ WordConstant(magic.multiplier, rep), rep);
2661 if (magic.multiplier < 0) {
2662 quotient =
__ WordAdd(quotient, left, rep);
2665 return __ WordAdd(
__ ShiftRightArithmetic(quotient, magic.shift, rep),
2669 return LowerToMul(
static_cast<int32_t
>(right),
2673 return LowerToMul(
static_cast<int64_t
>(right),
2682 return __ WordConstant(0, rep);
2697 left =
__ ShiftRightLogical(left, shift, rep);
2702 base::MagicNumbersForDivision<
decltype(right)>
const mag =
2704 V<Word> quotient =
__ UintMulOverflownBits(
2705 left,
__ WordConstant(mag.multiplier, rep), rep);
2710 quotient =
__ ShiftRightLogical(
2712 __ ShiftRightLogical(
__ WordSub(left, quotient, rep), 1, rep),
2714 mag.shift - 1, rep);
2716 quotient =
__ ShiftRightLogical(quotient, mag.shift, rep);
2721 return LowerToMul(
static_cast<uint32_t
>(right),
2725 return LowerToMul(
static_cast<uint64_t
>(right),
2734 bool reduced =
false;
2742 *negated = !*negated;
2750 *negated = !*negated;
2761 matcher_.MatchIntegralWord32Constant(right, &k2) && k1 == k2 &&
2777 matcher_.MatchIntegralWord32Constant(k2_index, &k2)) {
2778 k1 =
static_cast<uint32_t
>(k1_int);
2780 (
static_cast<uint64_t
>(k2) << k1 <=
2781 std::numeric_limits<uint32_t>::max())) {
2782 return __ Word32BitwiseAnd(
x, k2 << k1);
2790 if (left_val && right_val) {
2791 if (*left_val == *right_val) {
2793 return __ Word32Constant(*left_val);
2795 if (*left_val ==
false) {
2797 *negated = !*negated;
2806 return reduced ? std::optional<V<Word32>>(
condition) : std::nullopt;
2814 return std::nullopt;
2822 if (!map.has_value())
return false;
2824 if (map->IsJSObjectMap() && map->is_stable()) {
2830 if (map->instance_type() ==
2831 any_of(BIG_INT_BASE_TYPE, HEAP_NUMBER_TYPE, ODDBALL_TYPE)) {
2839 if (
x >= 0)
return false;
2840 if (
x == std::numeric_limits<int64_t>::min())
return true;
2843 return (x_abs & (x_abs - 1)) == 0;
2853#if V8_ENABLE_WEBASSEMBLY
#define REDUCE(operation)
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
V8_INLINE Address address() const
static constexpr int kMapOffset
static bool constexpr IsValid(T value)
void DependOnStableMap(MapRef map)
CompilationDependencies * dependencies() const
static constexpr FloatRepresentation Float32()
static constexpr FloatRepresentation Float64()
V< None > REDUCE Branch(OpIndex condition, Block *if_true, Block *if_false, BranchHint hint)
bool IsBit(V< Word > value)
V< None > REDUCE DeoptimizeIf(V< Word32 > condition, V< FrameState > frame_state, bool negated, const DeoptimizeParameters *parameters)
bool IsInt8(V< Word > value)
bool TryMatchHeapObject(V< Any > idx, int depth=0)
bool TryAdjustIndex(int32_t offset, OpIndex *index, const Operation &maybe_constant, uint8_t element_scale)
V< Word > ReduceWithTruncation(V< Word > value, uint64_t truncation_mask, WordRepresentation rep)
bool IsInt16(V< Word > value)
bool TryAdjustOffset(int32_t *offset, const Operation &maybe_constant, uint8_t element_scale, bool tagged_base)
static constexpr bool signalling_nan_possible
V< Word32 > REDUCE Comparison(V< Any > left, V< Any > right, ComparisonOp::Kind kind, RegisterRepresentation rep)
std::optional< V< Word > > TryReduceToRor(V< Word > left, V< Word > right, WordBinopOp::Kind kind, WordRepresentation rep)
V< Word > REDUCE WordUnary(V< Word > input, WordUnaryOp::Kind kind, WordRepresentation rep)
std::optional< V< Word32 > > ReduceBranchCondition(V< Word32 > condition, bool *negated)
uint64_t TruncateWord(uint64_t value, WordRepresentation rep)
V< Tuple< Word, Word32 > > REDUCE OverflowCheckedBinop(V< Word > left, V< Word > right, OverflowCheckedBinopOp::Kind kind, WordRepresentation rep)
V< Untagged > REDUCE Change(V< Untagged > input, ChangeOp::Kind kind, ChangeOp::Assumption assumption, RegisterRepresentation from, RegisterRepresentation to)
OpIndex ReduceMemoryIndex(OpIndex index, int32_t *offset, uint8_t *element_scale, bool tagged_base)
bool MapLoadCanBeConstantFolded(OptionalMapRef map)
static constexpr uint16_t CountLeadingSignBits(int64_t c, WordRepresentation rep)
V< Float32 > UndoFloat32ToFloat64Conversion(V< Float64 > value)
V< Word > REDUCE WordBinop(V< Word > left, V< Word > right, WordBinopOp::Kind kind, WordRepresentation rep)
bool IsFloat32ConvertedToFloat64(V< Any > value)
const OperationMatcher & matcher_
V< Word > TryRemoveWord32ToWord64Conversion(V< Word > value)
bool TryAdjustElementScale(uint8_t *element_scale, OpIndex maybe_constant)
V< Any > REDUCE TaggedBitcast(V< Any > input, RegisterRepresentation from, RegisterRepresentation to, TaggedBitcastOp::Kind kind)
bool IsWord32ConvertedToWord64(V< Any > value, std::optional< bool > *sign_extended=nullptr)
V< Word32 > UndoWord32ToWord64Conversion(V< Word > value)
V< Word > ReduceUnsignedDiv(V< Word > left, uint64_t right, WordRepresentation rep)
V< None > REDUCE Store(OpIndex base_idx, OptionalOpIndex index, OpIndex value, StoreOp::Kind kind, MemoryRepresentation stored_rep, WriteBarrierKind write_barrier, int32_t offset, uint8_t element_scale, bool maybe_initializing_or_transitioning, IndirectPointerTag maybe_indirect_pointer_tag)
std::optional< bool > MatchBoolConstant(V< Any > condition)
V< Word > ReduceSignedDiv(V< Word > left, int64_t right, WordRepresentation rep)
V< None > REDUCE Switch(V< Word32 > input, base::Vector< SwitchOp::Case > cases, Block *default_case, BranchHint default_hint)
V< Word32 > ReduceCompareEqual(V< Any > left, V< Any > right, RegisterRepresentation rep)
V< Float > REDUCE FloatBinop(V< Float > lhs, V< Float > rhs, FloatBinopOp::Kind kind, FloatRepresentation rep)
OpIndex REDUCE Load(OpIndex base_idx, OptionalOpIndex index, LoadOp::Kind kind, MemoryRepresentation loaded_rep, RegisterRepresentation result_rep, int32_t offset, uint8_t element_scale)
V< Float64 > REDUCE BitcastWord32PairToFloat64(V< Word32 > hi_word32, V< Word32 > lo_word32)
V< None > REDUCE StaticAssert(V< Word32 > condition, const char *source)
static constexpr bool IsNegativePowerOfTwo(int64_t x)
V< Float > REDUCE FloatUnary(V< Float > input, FloatUnaryOp::Kind kind, FloatRepresentation rep)
constexpr bool IsWord() const
uint64_t MaxUnsignedValue() const
constexpr uint16_t bit_width() const
constexpr bool IsFloat() const
static constexpr MemoryRepresentation Int8()
static constexpr MemoryRepresentation Uint32()
static constexpr MemoryRepresentation Int32()
static constexpr MemoryRepresentation Uint16()
static constexpr MemoryRepresentation Uint8()
static constexpr MemoryRepresentation Int16()
static constexpr OpIndex Invalid()
bool MatchConstantRightShift(V< Any > matched, V< T > *input, WordRepresentation rep, int *amount) const
bool MatchBitwiseAndWithConstant(V< Any > matched, V< T > *value, uint64_t *constant, WordRepresentation rep) const
bool MatchIntegralWord32Constant(V< Any > matched, uint32_t *constant) const
constexpr Enum value() const
static constexpr RegisterRepresentation Word32()
static constexpr RegisterRepresentation Float64()
static constexpr RegisterRepresentation WordPtr()
static constexpr RegisterRepresentation Float32()
static constexpr RegisterRepresentation Word64()
static constexpr RegisterRepresentation Tagged()
static V< T > Cast(V< U > index)
static constexpr WordRepresentation Word32()
constexpr int64_t MinSignedValue() const
static constexpr WordRepresentation WordPtr()
static constexpr WordRepresentation Word64()
constexpr uint64_t MaxUnsignedValue() const
static bool TryMatch16x8UpperToLowerReduce(const uint8_t *shuffle1, const uint8_t *shuffle2, const uint8_t *shuffle3)
static bool TryMatch32x4PairwiseReduce(const uint8_t *shuffle1, const uint8_t *shuffle2)
static bool TryMatch64x2Shuffle(const uint8_t *shuffle, uint8_t *shuffle64x2)
static bool TryMatch32x4UpperToLowerReduce(const uint8_t *shuffle1, const uint8_t *shuffle2)
static bool TryMatch64x2Reduce(const uint8_t *shuffle64x2)
static bool TryMatch8x16UpperToLowerReduce(const uint8_t *shuffle1, const uint8_t *shuffle2, const uint8_t *shuffle3, const uint8_t *shuffle4)
constexpr double kMaxDoubleRepresentableInt64
#define TURBOSHAFT_REDUCER_BOILERPLATE(Name)
#define LABEL_BLOCK(label)
TurboshaftPipelineKind pipeline_kind
std::optional< TNode< JSArray > > a
ZoneVector< RpoNumber > & result
InstructionOperand source
constexpr unsigned CountLeadingZeros(T value)
bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t *val)
constexpr uint64_t RotateRight64(uint64_t value, uint64_t shift)
int32_t SignedMulHigh32(int32_t lhs, int32_t rhs)
constexpr uint32_t RotateLeft32(uint32_t value, uint32_t shift)
constexpr unsigned CountTrailingZeros64(uint64_t value)
int32_t SignedDiv32(int32_t lhs, int32_t rhs)
int64_t SignedDiv64(int64_t lhs, int64_t rhs)
bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t *val)
constexpr unsigned CountTrailingZeros(T value)
constexpr unsigned CountPopulation(T value)
uint32_t UnsignedMulHigh32(uint32_t lhs, uint32_t rhs)
int64_t SignedMulHigh64(int64_t u, int64_t v)
constexpr bool IsPowerOfTwo(T value)
uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs)
uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs)
constexpr uint64_t RotateLeft64(uint64_t value, uint64_t shift)
constexpr uint32_t RotateRight32(uint32_t value, uint32_t shift)
constexpr std::make_unsigned_t< T > Unsigned(T value)
constexpr unsigned CountLeadingSignBits(T value)
int64_t SignedMod64(int64_t lhs, int64_t rhs)
uint64_t UnsignedDiv64(uint64_t lhs, uint64_t rhs)
bool SignedAddOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
uint64_t UnsignedMod64(uint64_t lhs, uint64_t rhs)
int32_t SignedMod32(int32_t lhs, int32_t rhs)
bool SignedSubOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t *val)
uint64_t UnsignedMulHigh64(uint64_t u, uint64_t v)
bool SignedMulOverflow64(int64_t lhs, int64_t rhs, int64_t *val)
constexpr int WhichPowerOfTwo(T value)
double atan2(double y, double x)
MagicNumbersForDivision< T > UnsignedDivisionByConstant(T d, unsigned leading_zeros)
V8_INLINE Dest bit_cast(Source const &source)
MagicNumbersForDivision< T > SignedDivisionByConstant(T d)
bool all_of(const C &container, const P &predicate)
constexpr uint64_t multi(const Ts &... values)
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
any_of(const Args &...) -> any_of< Args... >
all_of(const Args &...) -> all_of< Args... >
V8_EXPORT_PRIVATE bool ShouldSkipOptimizationStep()
Op * CreateOperation(base::SmallVector< OperationStorageSlot, 32 > &storage, Args... args)
BranchHint NegateBranchHint(BranchHint hint)
OptionalRef< typename ref_traits< T >::ref_type > TryMakeRef(JSHeapBroker *broker, ObjectData *data)
static const Operator * IntPtrConstant(CommonOperatorBuilder *common, intptr_t value)
double pow(double x, double y)
int32_t DoubleToInt32_NoInline(double x)
std::make_unsigned< T >::type Abs(T a)
bool Is(IndirectHandle< U > value)
double Modulo(double x, double y)
static const uint32_t K[64]
float DoubleToFloat32_NoInline(double x)
float DoubleToFloat32(double x)
const intptr_t kSmiTagMask
bool is_signed(Condition cond)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
@ kUnsignedLessThanOrEqual
int64_t signed_integral() const
static bool IsCommutative(Kind kind)
static V8_EXPORT_PRIVATE bool IsSupported(Kind kind, FloatRepresentation rep)
static constexpr bool OffsetIsValid(int32_t offset, bool tagged_base)
const uint16_t input_count
const underlying_operation_t< Op > * TryCast() const
underlying_operation_t< Op > & Cast()
static bool IsCommutative(Kind kind)
V< Word32 > right() const
bool IsCommutative() const
@ kUnsignedMulOverflownBits
@ kSignedMulOverflownBits
static bool IsAssociative(Kind kind)
std::optional< BitfieldCheck > TryCombine(const BitfieldCheck &other)
static std::optional< BitfieldCheck > TryDetectShiftAndMaskOneBit(const OperationMatcher &matcher, V< Word > index)
static std::optional< BitfieldCheck > Detect(const OperationMatcher &matcher, const Graph &graph, V< Word > index)
uint32_t const masked_value
bool const truncate_from_64_bit
BitfieldCheck(V< Word > source, uint32_t mask, uint32_t masked_value, bool truncate_from_64_bit)