@@ -502,7 +502,6 @@ struct InstrAttrs {
502502 M (UnboxInt64, kNoGC ) \
503503 M (CaseInsensitiveCompare, kNoGC ) \
504504 M (BinaryInt64Op, kNoGC ) \
505- M (ShiftInt64Op, kNoGC ) \
506505 M (UnaryInt64Op, kNoGC ) \
507506 M (CheckArrayBound, kNoGC ) \
508507 M (GenericCheckBound, kNoGC ) \
@@ -527,7 +526,6 @@ struct InstrAttrs {
527526 M (UnboxLane, kNoGC ) \
528527 M (BoxLanes, _) \
529528 M (BinaryUint32Op, kNoGC ) \
530- M (ShiftUint32Op, kNoGC ) \
531529 M (UnaryUint32Op, kNoGC ) \
532530 M (BoxUint32, _) \
533531 M (UnboxUint32, kNoGC ) \
@@ -564,7 +562,6 @@ struct InstrAttrs {
564562 M (Condition, _) \
565563 M (InstanceCallBase, _) \
566564 M (ReturnBase, _) \
567- M (ShiftIntegerOp, _) \
568565 M (UnaryIntegerOp, _) \
569566 M (UnboxInteger, _)
570567
@@ -8737,7 +8734,7 @@ class UnboxInt64Instr : public UnboxIntegerInstr {
87378734
87388735bool Definition::IsInt64Definition () {
87398736 return (Type ()->ToCid () == kMintCid ) || IsBinaryInt64Op () ||
8740- IsUnaryInt64Op () || IsShiftInt64Op () || IsBoxInt64 () || IsUnboxInt64 ();
8737+ IsUnaryInt64Op () || IsBoxInt64 () || IsUnboxInt64 ();
87418738}
87428739
87438740// Calls into the runtime and performs a case-insensitive comparison of the
@@ -9234,6 +9231,9 @@ class BinaryIntegerOpInstr : public TemplateDefinition<2, NoThrow, Pure> {
92349231 // that does not include the possibility of being zero.
92359232 bool RightIsNonZero () const ;
92369233
9234+ // Returns true if rhs operand is positive.
9235+ bool RightIsPositive () const ;
9236+
92379237 // Returns true if right is a non-zero Smi constant which absolute value is
92389238 // a power of two.
92399239 bool RightIsPowerOfTwoConstant () const ;
@@ -9267,6 +9267,12 @@ class BinaryIntegerOpInstr : public TemplateDefinition<2, NoThrow, Pure> {
92679267 const Range* right_range,
92689268 Range* range);
92699269
9270+ static constexpr intptr_t kShiftCountLimit = 63 ;
9271+
9272+ // Returns true if the shift amount (right operand) is guaranteed to be in
9273+ // [0..max] range.
9274+ bool IsShiftCountInRange (int64_t max = kShiftCountLimit ) const ;
9275+
92709276 private:
92719277 Definition* CreateConstantResult (FlowGraph* graph, const Integer& result);
92729278
@@ -9388,6 +9394,9 @@ class BinaryUint32OpInstr : public BinaryIntegerOpInstr {
93889394 case Token::kBIT_AND :
93899395 case Token::kBIT_OR :
93909396 case Token::kBIT_XOR :
9397+ case Token::kSHL :
9398+ case Token::kSHR :
9399+ case Token::kUSHR :
93919400 return true ;
93929401 default :
93939402 return false ;
@@ -9399,6 +9408,10 @@ class BinaryUint32OpInstr : public BinaryIntegerOpInstr {
93999408 DECLARE_EMPTY_SERIALIZATION (BinaryUint32OpInstr, BinaryIntegerOpInstr)
94009409
94019410 private:
9411+ static constexpr intptr_t kUint32ShiftCountLimit = 31 ;
9412+
9413+ void EmitShiftUint32 (FlowGraphCompiler* compiler);
9414+
94029415 DISALLOW_COPY_AND_ASSIGN (BinaryUint32OpInstr);
94039416};
94049417
@@ -9417,9 +9430,24 @@ class BinaryInt64OpInstr : public BinaryIntegerOpInstr {
94179430 return false ;
94189431 }
94199432
9433+ virtual bool ComputeCanDeoptimizeAfterCall () const {
9434+ return ((op_kind () == Token::kSHL ) || (op_kind () == Token::kSHR ) ||
9435+ (op_kind () == Token::kUSHR )) &&
9436+ !CompilerState::Current ().is_aot ();
9437+ }
9438+
94209439 virtual bool MayThrow () const {
9421- return (op_kind () == Token::kMOD || op_kind () == Token::kTRUNCDIV ) &&
9422- !RightIsNonZero ();
9440+ switch (op_kind ()) {
9441+ case Token::kSHL :
9442+ case Token::kSHR :
9443+ case Token::kUSHR :
9444+ return !IsShiftCountInRange ();
9445+ case Token::kMOD :
9446+ case Token::kTRUNCDIV :
9447+ return !RightIsNonZero ();
9448+ default :
9449+ return false ;
9450+ }
94239451 }
94249452
94259453 virtual Representation representation () const { return kUnboxedInt64 ; }
@@ -9434,118 +9462,9 @@ class BinaryInt64OpInstr : public BinaryIntegerOpInstr {
94349462 DECLARE_EMPTY_SERIALIZATION (BinaryInt64OpInstr, BinaryIntegerOpInstr)
94359463
94369464 private:
9437- DISALLOW_COPY_AND_ASSIGN (BinaryInt64OpInstr);
9438- };
9439-
9440- // Base class for integer shift operations.
9441- class ShiftIntegerOpInstr : public BinaryIntegerOpInstr {
9442- public:
9443- ShiftIntegerOpInstr (Token::Kind op_kind,
9444- Value* left,
9445- Value* right,
9446- intptr_t deopt_id,
9447- // Provided by BinaryIntegerOpInstr::Make for constant RHS
9448- Range* right_range = nullptr )
9449- : BinaryIntegerOpInstr(op_kind, left, right, deopt_id),
9450- shift_range_ (right_range) {
9451- ASSERT ((op_kind == Token::kSHL ) || (op_kind == Token::kSHR ) ||
9452- (op_kind == Token::kUSHR ));
9453- mark_truncating ();
9454- }
9455-
9456- Range* shift_range () const { return shift_range_; }
9457-
9458- // Set the range directly (takes ownership).
9459- void set_shift_range (Range* shift_range) { shift_range_ = shift_range; }
9460-
9461- virtual void InferRange (RangeAnalysis* analysis, Range* range);
9462-
9463- DECLARE_ABSTRACT_INSTRUCTION (ShiftIntegerOp)
9464-
9465- #define FIELD_LIST (F ) F(Range*, shift_range_)
9466-
9467- DECLARE_INSTRUCTION_SERIALIZABLE_FIELDS (ShiftIntegerOpInstr,
9468- BinaryIntegerOpInstr,
9469- FIELD_LIST)
9470- #undef FIELD_LIST
9471-
9472- protected:
9473- static constexpr intptr_t kShiftCountLimit = 63 ;
9474-
9475- // Returns true if the shift amount is guaranteed to be in
9476- // [0..max] range.
9477- bool IsShiftCountInRange (int64_t max = kShiftCountLimit ) const ;
9478-
9479- private:
9480- DISALLOW_COPY_AND_ASSIGN (ShiftIntegerOpInstr);
9481- };
9482-
9483- // Non-speculative int64 shift. Takes 2 unboxed int64.
9484- // Throws if right operand is negative.
9485- class ShiftInt64OpInstr : public ShiftIntegerOpInstr {
9486- public:
9487- ShiftInt64OpInstr (Token::Kind op_kind,
9488- Value* left,
9489- Value* right,
9490- intptr_t deopt_id,
9491- Range* right_range = nullptr )
9492- : ShiftIntegerOpInstr(op_kind, left, right, deopt_id, right_range) {}
9493-
9494- virtual bool ComputeCanDeoptimize () const { return false ; }
9495- virtual bool ComputeCanDeoptimizeAfterCall () const {
9496- return !CompilerState::Current ().is_aot ();
9497- }
9498- virtual bool MayThrow () const { return !IsShiftCountInRange (); }
9499-
9500- virtual Representation representation () const { return kUnboxedInt64 ; }
9501-
9502- virtual Representation RequiredInputRepresentation (intptr_t idx) const {
9503- ASSERT ((idx == 0 ) || (idx == 1 ));
9504- return kUnboxedInt64 ;
9505- }
9506-
9507- DECLARE_INSTRUCTION (ShiftInt64Op)
9508-
9509- DECLARE_EMPTY_SERIALIZATION (ShiftInt64OpInstr, ShiftIntegerOpInstr)
9510-
9511- private:
9512- DISALLOW_COPY_AND_ASSIGN (ShiftInt64OpInstr);
9513- };
9514-
9515- // Non-speculative uint32 shift. Takes unboxed uint32 and unboxed int64.
9516- // Throws if right operand is negative.
9517- class ShiftUint32OpInstr : public ShiftIntegerOpInstr {
9518- public:
9519- ShiftUint32OpInstr (Token::Kind op_kind,
9520- Value* left,
9521- Value* right,
9522- intptr_t deopt_id,
9523- Range* right_range = nullptr )
9524- : ShiftIntegerOpInstr(op_kind, left, right, deopt_id, right_range) {}
9525-
9526- virtual bool ComputeCanDeoptimize () const { return false ; }
9527- virtual bool ComputeCanDeoptimizeAfterCall () const {
9528- return !CompilerState::Current ().is_aot ();
9529- }
9530- virtual bool MayThrow () const {
9531- return !IsShiftCountInRange (kUint32ShiftCountLimit );
9532- }
9533-
9534- virtual Representation representation () const { return kUnboxedUint32 ; }
9535-
9536- virtual Representation RequiredInputRepresentation (intptr_t idx) const {
9537- ASSERT ((idx == 0 ) || (idx == 1 ));
9538- return (idx == 0 ) ? kUnboxedUint32 : kUnboxedInt64 ;
9539- }
9540-
9541- DECLARE_INSTRUCTION (ShiftUint32Op)
9542-
9543- DECLARE_EMPTY_SERIALIZATION (ShiftUint32OpInstr, ShiftIntegerOpInstr)
9544-
9545- private:
9546- static constexpr intptr_t kUint32ShiftCountLimit = 31 ;
9465+ void EmitShiftInt64 (FlowGraphCompiler* compiler);
95479466
9548- DISALLOW_COPY_AND_ASSIGN (ShiftUint32OpInstr );
9467+ DISALLOW_COPY_AND_ASSIGN (BinaryInt64OpInstr );
95499468};
95509469
95519470class UnaryDoubleOpInstr : public TemplateDefinition <1 , NoThrow, Pure> {
0 commit comments