Commit 64eae3fc authored by Jacob.Bramley@arm.com's avatar Jacob.Bramley@arm.com

ARM64: Slightly simplify LShiftI and LShiftS.

BUG=
R=ulan@chromium.org

Review URL: https://codereview.chromium.org/494053002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23277 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 37d886bc
......@@ -2203,8 +2203,7 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
return DoArithmeticT(op, instr);
}
DCHECK(instr->representation().IsInteger32() ||
instr->representation().IsSmi());
DCHECK(instr->representation().IsSmiOrInteger32());
DCHECK(instr->left()->representation().Equals(instr->representation()));
DCHECK(instr->right()->representation().Equals(instr->representation()));
......@@ -2215,42 +2214,30 @@ LInstruction* LChunkBuilder::DoShift(Token::Value op,
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);
constant_value = JSShiftAmountFromHConstant(right_value);
} 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
// result cannot be truncated to int32.
bool does_deopt = false;
if ((op == Token::SHR) && (constant_value == 0)) {
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
// The only shift that can deoptimize is `left >>> 0`, where left is negative.
// In these cases, the result is a uint32 that is too large for an int32.
bool right_can_be_zero = !instr->right()->IsConstant() ||
(JSShiftAmountFromHConstant(instr->right()) == 0);
bool can_deopt = false;
if ((op == Token::SHR) && right_can_be_zero) {
if (FLAG_opt_safe_uint32_operations) {
does_deopt = !instr->CheckFlag(HInstruction::kUint32);
can_deopt = !instr->CheckFlag(HInstruction::kUint32);
} else {
does_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
can_deopt = !instr->CheckUsesForFlag(HValue::kTruncatingToInt32);
}
}
LInstruction* result;
if (instr->representation().IsInteger32()) {
result = DefineAsRegister(new(zone()) LShiftI(op, left, right, does_deopt));
result = DefineAsRegister(new (zone()) LShiftI(op, left, right, can_deopt));
} else {
DCHECK(instr->representation().IsSmi());
result = DefineAsRegister(
new(zone()) LShiftS(op, left, right, temp, does_deopt));
result = DefineAsRegister(new (zone()) LShiftS(op, left, right, can_deopt));
}
return does_deopt ? AssignEnvironment(result) : result;
return can_deopt ? AssignEnvironment(result) : result;
}
......
......@@ -2733,19 +2733,17 @@ class LShiftI V8_FINAL : public LTemplateInstruction<1, 2, 0> {
};
class LShiftS V8_FINAL : public LTemplateInstruction<1, 2, 1> {
class LShiftS V8_FINAL : public LTemplateInstruction<1, 2, 0> {
public:
LShiftS(Token::Value op, LOperand* left, LOperand* right, LOperand* temp,
bool can_deopt) : op_(op), can_deopt_(can_deopt) {
LShiftS(Token::Value op, LOperand* left, LOperand* right, 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")
......
......@@ -4926,32 +4926,33 @@ void LCodeGen::DoShiftS(LShiftS* instr) {
Register left = ToRegister(instr->left());
Register result = ToRegister(instr->result());
// Only ROR by register needs a temp.
DCHECK(((instr->op() == Token::ROR) && right_op->IsRegister()) ||
(instr->temp() == NULL));
if (right_op->IsRegister()) {
Register right = ToRegister(instr->right());
// JavaScript shifts only look at the bottom 5 bits of the 'right' operand.
// Since we're handling smis in X registers, we have to extract these bits
// explicitly.
__ Ubfx(result, right, kSmiShift, 5);
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());
// This is the only case that needs a scratch register. To keep things
// simple for the other cases, borrow a MacroAssembler scratch register.
UseScratchRegisterScope temps(masm());
Register temp = temps.AcquireW();
__ SmiUntag(temp, left);
__ Ror(result.W(), temp.W(), result.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:
__ Ubfx(result, right, kSmiShift, 5);
__ Lsr(result, left, result);
__ Bic(result, result, kSmiShiftMask);
if (instr->can_deopt()) {
......
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