Revision: 19117
Author:   [email protected]
Date:     Wed Feb  5 18:45:42 2014 UTC
Log:      A64: Implement LShiftS

BUG=
[email protected]

Review URL: https://codereview.chromium.org/151163006
http://code.google.com/p/v8/source/detail?r=19117

Modified:
 /branches/experimental/a64/src/a64/lithium-a64.cc
 /branches/experimental/a64/src/a64/lithium-a64.h
 /branches/experimental/a64/src/a64/lithium-codegen-a64.cc

=======================================
--- /branches/experimental/a64/src/a64/lithium-a64.cc Wed Feb 5 17:41:02 2014 UTC +++ /branches/experimental/a64/src/a64/lithium-a64.cc Wed Feb 5 18:45:42 2014 UTC
@@ -2018,18 +2018,22 @@

 LInstruction* LChunkBuilder::DoShift(Token::Value op,
                                      HBitwiseBinaryOperation* instr) {
-  // TODO(jbramley): Support smis inline, like integers.
-  if (instr->representation().IsSmiOrTagged()) {
+  if (instr->representation().IsTagged()) {
     return DoArithmeticT(op, instr);
   }

-  ASSERT(instr->representation().IsInteger32());
+  ASSERT(instr->representation().IsInteger32() ||
+         instr->representation().IsSmi());
   ASSERT(instr->left()->representation().Equals(instr->representation()));
   ASSERT(instr->right()->representation().Equals(instr->representation()));
-  LOperand* left = UseRegisterAtStart(instr->left());
+
+  LOperand* left = instr->representation().IsSmi()
+      ? UseRegister(instr->left())
+      : UseRegisterAtStart(instr->left());

   HValue* right_value = instr->right();
   LOperand* right = NULL;
+  LOperand* temp = NULL;
   int constant_value = 0;
   if (right_value->IsConstant()) {
     right = UseConstant(right_value);
@@ -2037,6 +2041,9 @@
     constant_value = constant->Integer32Value() & 0x1f;
   } else {
     right = UseRegisterAtStart(right_value);
+    if (op == Token::ROR) {
+      temp = TempRegister();
+    }
   }

// Shift operations can only deoptimize if we do a logical shift by 0 and the
@@ -2050,8 +2057,15 @@
     }
   }

-  LInstruction* result =
-      DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
+  LInstruction* result;
+  if (instr->representation().IsInteger32()) {
+ result = DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
+  } else {
+    ASSERT(instr->representation().IsSmi());
+    result = DefineAsRegister(
+        new(zone()) LShiftS(op, left, right, temp, does_deopt));
+  }
+
   return does_deopt ? AssignEnvironment(result) : result;
 }

=======================================
--- /branches/experimental/a64/src/a64/lithium-a64.h Wed Feb 5 17:41:02 2014 UTC +++ /branches/experimental/a64/src/a64/lithium-a64.h Wed Feb 5 18:45:42 2014 UTC
@@ -163,6 +163,7 @@
   V(Return)                                     \
   V(SeqStringSetChar)                           \
   V(ShiftI)                                     \
+  V(ShiftS)                                     \
   V(SmiTag)                                     \
   V(SmiUntag)                                   \
   V(StackCheck)                                 \
@@ -2469,6 +2470,29 @@
 };


+class LShiftS V8_FINAL : public LTemplateInstruction<1, 2, 1> {
+ public:
+  LShiftS(Token::Value op, LOperand* left, LOperand* right, LOperand* temp,
+          bool can_deopt) : op_(op), can_deopt_(can_deopt) {
+    inputs_[0] = left;
+    inputs_[1] = right;
+    temps_[0] = temp;
+  }
+
+  Token::Value op() const { return op_; }
+  LOperand* left() { return inputs_[0]; }
+  LOperand* right() { return inputs_[1]; }
+  LOperand* temp() { return temps_[0]; }
+  bool can_deopt() const { return can_deopt_; }
+
+  DECLARE_CONCRETE_INSTRUCTION(ShiftS, "shift-s")
+
+ private:
+  Token::Value op_;
+  bool can_deopt_;
+};
+
+
 class LStoreCodeEntry V8_FINAL: public LTemplateInstruction<0, 2, 1> {
  public:
   LStoreCodeEntry(LOperand* function, LOperand* code_object,
=======================================
--- /branches/experimental/a64/src/a64/lithium-codegen-a64.cc Wed Feb 5 17:41:02 2014 UTC +++ /branches/experimental/a64/src/a64/lithium-codegen-a64.cc Wed Feb 5 18:45:42 2014 UTC
@@ -4515,10 +4515,6 @@
       case Token::SHL: __ Lsl(result, left, right); break;
       case Token::SHR:
         if (instr->can_deopt()) {
-          // TODO(all): Using conditional compare may be faster here, eg.
-          // Deopt if (right == 0) && (left < 0).
-          // __ Cmp(right, 0);
-          // __ Ccmp(left, 0, NoFlag, eq);
           Label right_not_zero;
           __ Cbnz(right, &right_not_zero);
           DeoptimizeIfNegative(left, instr->environment());
@@ -4547,6 +4543,81 @@
     }
   }
 }
+
+
+void LCodeGen::DoShiftS(LShiftS* instr) {
+  LOperand* right_op = instr->right();
+  Register left = ToRegister(instr->left());
+  Register result = ToRegister(instr->result());
+
+  // Only ROR by register needs a temp.
+  ASSERT(((instr->op() == Token::ROR) && right_op->IsRegister()) ||
+         (instr->temp() == NULL));
+
+  if (right_op->IsRegister()) {
+    Register right = ToRegister(instr->right());
+    switch (instr->op()) {
+      case Token::ROR: {
+        Register temp = ToRegister(instr->temp());
+        __ Ubfx(temp, right, kSmiShift, 5);
+        __ SmiUntag(result, left);
+        __ Ror(result.W(), result.W(), temp.W());
+        __ SmiTag(result);
+        break;
+      }
+      case Token::SAR:
+        __ Ubfx(result, right, kSmiShift, 5);
+        __ Asr(result, left, result);
+        __ Bic(result, result, kSmiShiftMask);
+        break;
+      case Token::SHL:
+        __ Ubfx(result, right, kSmiShift, 5);
+        __ Lsl(result, left, result);
+        break;
+      case Token::SHR:
+        if (instr->can_deopt()) {
+          Label right_not_zero;
+          __ Cbnz(right, &right_not_zero);
+          DeoptimizeIfNegative(left, instr->environment());
+          __ Bind(&right_not_zero);
+        }
+        __ Ubfx(result, right, kSmiShift, 5);
+        __ Lsr(result, left, result);
+        __ Bic(result, result, kSmiShiftMask);
+        break;
+      default: UNREACHABLE();
+    }
+  } else {
+    ASSERT(right_op->IsConstantOperand());
+    int shift_count = ToInteger32(LConstantOperand::cast(right_op)) & 0x1f;
+    if (shift_count == 0) {
+      if ((instr->op() == Token::SHR) && instr->can_deopt()) {
+        DeoptimizeIfNegative(left, instr->environment());
+      }
+      __ Mov(result, left);
+    } else {
+      switch (instr->op()) {
+        case Token::ROR:
+          __ SmiUntag(result, left);
+          __ Ror(result.W(), result.W(), shift_count);
+          __ SmiTag(result);
+          break;
+        case Token::SAR:
+          __ Asr(result, left, shift_count);
+          __ Bic(result, result, kSmiShiftMask);
+          break;
+        case Token::SHL:
+          __ Lsl(result, left, shift_count);
+          break;
+        case Token::SHR:
+          __ Lsr(result, left, shift_count);
+          __ Bic(result, result, kSmiShiftMask);
+          break;
+        default: UNREACHABLE();
+      }
+    }
+  }
+}


 void LCodeGen::DoDebugBreak(LDebugBreak* instr) {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to