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
This commit is contained in:
parent
37d886bc09
commit
64eae3fc3c
@ -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());
|
||||
LOperand* right = UseRegisterOrConstantAtStart(instr->right());
|
||||
|
||||
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)) {
|
||||
// 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()) {
|
||||
|
Loading…
Reference in New Issue
Block a user