44
55#include " jit/MIR.h"
66
7+ #include " mozilla/Casting.h"
78#include " mozilla/FloatingPoint.h"
89#include " mozilla/MathAlgorithms.h"
910#include " mozilla/Maybe.h"
@@ -5700,6 +5701,80 @@ MDefinition* MCompare::tryFoldStringIndexOf(TempAllocator& alloc) {
57005701 return MNot::New (alloc, startsWith);
57015702}
57025703
5704+ /* *
5705+ * Most architectures can generate smaller code for comparison against zero, so
5706+ * the macro-assemblers special-case a zero immediate when emitting
5707+ * compare-and-branch instructions.
5708+ *
5709+ * Some comparisons against one resp. negative one can instead be written as a
5710+ * comparison against zero. Handle these cases here to avoid duplicating the
5711+ * same code across all architectures.
5712+ */
5713+ static bool CanCompareAgainstZero (int64_t value, JSOp op, bool isSigned) {
5714+ switch (op) {
5715+ case JSOp::Lt:
5716+ case JSOp::Ge:
5717+ // Can rewrite |operand < 1| as |operand <= 0|.
5718+ // Can rewrite |operand >= 1| as |operand > 0|.
5719+ return value == 1 ;
5720+
5721+ case JSOp::Le:
5722+ case JSOp::Gt:
5723+ // Can rewrite |operand <= -1| as |operand < 0|.
5724+ // Can rewrite |operand > -1| as |operand >= 0|.
5725+ return isSigned && value == -1 ;
5726+
5727+ default :
5728+ return false ;
5729+ }
5730+ }
5731+
5732+ MCompare* MCompare::newCompareInt (TempAllocator& alloc, MDefinition* operand,
5733+ int64_t value, JSOp op, bool isSigned) {
5734+ MOZ_ASSERT (IsIntType (operand->type ()) || operand->type () == MIRType::BigInt);
5735+ MOZ_ASSERT_IF (operand->type () == MIRType::BigInt, isSigned);
5736+
5737+ // Prefer comparison against zero if possible.
5738+ if (CanCompareAgainstZero (value, op, isSigned)) {
5739+ value = 0 ;
5740+
5741+ // Update operator: (Lt -> Le), (Le -> Lt), (Gt -> Ge), (Ge -> Gt).
5742+ op = ReverseCompareOp (NegateCompareOp (op));
5743+ }
5744+
5745+ MConstant* cst;
5746+ CompareType compareType;
5747+ switch (operand->type ()) {
5748+ case MIRType::Int32:
5749+ cst = MConstant::NewInt32 (alloc, mozilla::AssertedCast<int32_t >(value));
5750+ compareType = isSigned ? Compare_Int32 : Compare_UInt32;
5751+ break ;
5752+
5753+ case MIRType::Int64:
5754+ cst = MConstant::NewInt64 (alloc, value);
5755+ compareType = isSigned ? Compare_Int64 : Compare_UInt64;
5756+ break ;
5757+
5758+ case MIRType::IntPtr:
5759+ cst = MConstant::NewIntPtr (alloc, mozilla::AssertedCast<intptr_t >(value));
5760+ compareType = isSigned ? Compare_IntPtr : Compare_UIntPtr;
5761+ break ;
5762+
5763+ case MIRType::BigInt:
5764+ cst = MConstant::NewInt32 (alloc, mozilla::AssertedCast<int32_t >(value));
5765+ compareType = Compare_BigInt_Int32;
5766+ break ;
5767+
5768+ default :
5769+ MOZ_CRASH (" unexpected operand type" );
5770+ }
5771+ block ()->insertBefore (this , cst);
5772+
5773+ auto * ins = MCompare::New (alloc, operand, cst, op, compareType);
5774+ ins->setResultType (type ());
5775+ return ins;
5776+ }
5777+
57035778MDefinition* MCompare::tryFoldBigInt64 (TempAllocator& alloc) {
57045779 if (compareType () == Compare_BigInt) {
57055780 auto * left = lhs ();
@@ -5797,17 +5872,11 @@ MDefinition* MCompare::tryFoldBigInt64(TempAllocator& alloc) {
57975872 return MConstant::NewBoolean (alloc, result);
57985873 }
57995874
5800- auto * cst = MConstant::NewInt64 (alloc, *value);
5801- block ()->insertBefore (this , cst);
5802-
5803- auto compareType =
5804- isSigned ? MCompare::Compare_Int64 : MCompare::Compare_UInt64;
5805- if (left == int64ToBigInt) {
5806- return MCompare::New (alloc, int64ToBigInt->input (), cst, jsop_,
5807- compareType);
5875+ JSOp op = jsop ();
5876+ if (right == int64ToBigInt) {
5877+ op = ReverseCompareOp (op);
58085878 }
5809- return MCompare::New (alloc, cst, int64ToBigInt->input (), jsop_,
5810- compareType);
5879+ return newCompareInt (alloc, int64ToBigInt->input (), *value, op, isSigned);
58115880 }
58125881
58135882 if (compareType () == Compare_BigInt_Int32) {
@@ -5833,13 +5902,8 @@ MDefinition* MCompare::tryFoldBigInt64(TempAllocator& alloc) {
58335902 return MConstant::NewBoolean (alloc, result);
58345903 }
58355904
5836- auto * cst = MConstant::NewInt64 (alloc, int64_t (constInt32));
5837- block ()->insertBefore (this , cst);
5838-
5839- auto compareType =
5840- isSigned ? MCompare::Compare_Int64 : MCompare::Compare_UInt64;
5841- return MCompare::New (alloc, int64ToBigInt->input (), cst, jsop_,
5842- compareType);
5905+ return newCompareInt (alloc, int64ToBigInt->input (), constInt32, jsop (),
5906+ isSigned);
58435907 }
58445908
58455909 return this ;
@@ -5894,17 +5958,11 @@ MDefinition* MCompare::tryFoldBigIntPtr(TempAllocator& alloc) {
58945958 return MConstant::NewBoolean (alloc, result);
58955959 }
58965960
5897- auto * cst = MConstant::NewIntPtr (alloc, value);
5898- block ()->insertBefore (this , cst);
5899-
5900- if (left == intPtrToBigInt) {
5901- left = intPtrToBigInt->input ();
5902- right = cst;
5903- } else {
5904- left = cst;
5905- right = intPtrToBigInt->input ();
5961+ JSOp op = jsop ();
5962+ if (right == intPtrToBigInt) {
5963+ op = ReverseCompareOp (op);
59065964 }
5907- return MCompare::New (alloc, left, right, jsop_, MCompare::Compare_IntPtr );
5965+ return newCompareInt (alloc, intPtrToBigInt-> input (), value, op );
59085966 }
59095967
59105968 if (compareType () == Compare_BigInt_Int32) {
@@ -5919,12 +5977,8 @@ MDefinition* MCompare::tryFoldBigIntPtr(TempAllocator& alloc) {
59195977 return this ;
59205978 }
59215979
5922- auto * cst =
5923- MConstant::NewIntPtr (alloc, intptr_t (right->toConstant ()->toInt32 ()));
5924- block ()->insertBefore (this , cst);
5925-
5926- return MCompare::New (alloc, left->toIntPtrToBigInt ()->input (), cst, jsop_,
5927- MCompare::Compare_IntPtr);
5980+ return newCompareInt (alloc, left->toIntPtrToBigInt ()->input (),
5981+ right->toConstant ()->toInt32 (), jsop ());
59285982 }
59295983
59305984 return this ;
@@ -5956,9 +6010,6 @@ MDefinition* MCompare::tryFoldBigInt(TempAllocator& alloc) {
59566010 return this ;
59576011 }
59586012
5959- MConstant* int32Const = MConstant::NewInt32 (alloc, x);
5960- block ()->insertBefore (this , int32Const);
5961-
59626013 auto op = jsop ();
59636014 if (IsStrictEqualityOp (op)) {
59646015 // Compare_BigInt_Int32 is only valid for loose comparison.
@@ -5967,9 +6018,87 @@ MDefinition* MCompare::tryFoldBigInt(TempAllocator& alloc) {
59676018 // Reverse the comparison operator if the operands were reordered.
59686019 op = ReverseCompareOp (op);
59696020 }
6021+ return newCompareInt (alloc, operand, x, op);
6022+ }
6023+
6024+ MDefinition* MCompare::tryFoldIntZero (TempAllocator& alloc) {
6025+ // Expect signed or unsigned integer relational comparison.
6026+ if (!IsRelationalOp (jsop ())) {
6027+ return this ;
6028+ }
59706029
5971- return MCompare::New (alloc, operand, int32Const, op,
5972- MCompare::Compare_BigInt_Int32);
6030+ bool isSigned;
6031+ switch (compareType ()) {
6032+ case Compare_Int32:
6033+ case Compare_Int64:
6034+ case Compare_IntPtr:
6035+ isSigned = true ;
6036+ break ;
6037+
6038+ case Compare_UInt32:
6039+ case Compare_UInt64:
6040+ case Compare_UIntPtr:
6041+ isSigned = false ;
6042+ break ;
6043+
6044+ case Compare_Undefined:
6045+ case Compare_Null:
6046+ case Compare_Double:
6047+ case Compare_Float32:
6048+ case Compare_String:
6049+ case Compare_Symbol:
6050+ case Compare_Object:
6051+ case Compare_BigInt:
6052+ case Compare_BigInt_Int32:
6053+ case Compare_BigInt_Double:
6054+ case Compare_BigInt_String:
6055+ case Compare_WasmAnyRef:
6056+ return this ;
6057+ }
6058+
6059+ auto * left = lhs ();
6060+ auto * right = rhs ();
6061+
6062+ // Both operands have the same Int type.
6063+ MOZ_ASSERT (left->type () == right->type ());
6064+ MOZ_ASSERT (IsIntType (left->type ()));
6065+
6066+ // One operand must be a constant.
6067+ if (!left->isConstant () && !right->isConstant ()) {
6068+ return this ;
6069+ }
6070+
6071+ auto * constant =
6072+ left->isConstant () ? left->toConstant () : right->toConstant ();
6073+ auto * operand = left->isConstant () ? right : left;
6074+
6075+ int64_t value;
6076+ switch (constant->type ()) {
6077+ case MIRType::Int32:
6078+ value = constant->toInt32 ();
6079+ break ;
6080+
6081+ case MIRType::Int64:
6082+ value = constant->toInt64 ();
6083+ break ;
6084+
6085+ case MIRType::IntPtr:
6086+ value = constant->toIntPtr ();
6087+ break ;
6088+
6089+ default :
6090+ MOZ_CRASH (" unexpected int type" );
6091+ }
6092+
6093+ auto op = jsop ();
6094+ if (operand == right) {
6095+ op = ReverseCompareOp (op);
6096+ }
6097+
6098+ if (!CanCompareAgainstZero (value, op, isSigned)) {
6099+ return this ;
6100+ }
6101+ return newCompareInt (alloc, operand, value, op, isSigned);
59736102}
59746103
59756104MDefinition* MCompare::foldsTo (TempAllocator& alloc) {
@@ -6016,6 +6145,10 @@ MDefinition* MCompare::foldsTo(TempAllocator& alloc) {
60166145 return folded;
60176146 }
60186147
6148+ if (MDefinition* folded = tryFoldIntZero (alloc); folded != this ) {
6149+ return folded;
6150+ }
6151+
60196152 return this ;
60206153}
60216154
0 commit comments