Commit 663f8fa2 authored by erik.corry@gmail.com's avatar erik.corry@gmail.com

ARM: Optimize shifts by constant integers, especially

shifts by zero or arithmetic shifts.  Updated to also
eliminate ASR followed by LSL as per part two of
http://codereview.chromium.org/1987008/show
Review URL: http://codereview.chromium.org/2054007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4641 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 764dc665
......@@ -1146,44 +1146,66 @@ void CodeGenerator::SmiOperation(Token::Value op,
int shift_value = int_value & 0x1f; // least significant 5 bits
DeferredCode* deferred =
new DeferredInlineSmiOperation(op, shift_value, false, mode, tos);
__ tst(tos, Operand(kSmiTagMask));
deferred->Branch(ne);
__ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // remove tags
uint32_t problematic_mask = kSmiTagMask;
// For unsigned shift by zero all negative smis are problematic.
if (shift_value == 0 && op == Token::SHR) problematic_mask |= 0x80000000;
__ tst(tos, Operand(problematic_mask));
deferred->Branch(ne); // Go slow for problematic input.
switch (op) {
case Token::SHL: {
if (shift_value != 0) {
__ mov(scratch, Operand(scratch, LSL, shift_value));
int adjusted_shift = shift_value - kSmiTagSize;
ASSERT(adjusted_shift >= 0);
if (adjusted_shift != 0) {
__ mov(scratch, Operand(tos, LSL, adjusted_shift));
// Check that the *signed* result fits in a smi.
__ add(scratch2, scratch, Operand(0x40000000), SetCC);
deferred->Branch(mi);
__ mov(tos, Operand(scratch, LSL, kSmiTagSize));
} else {
// Check that the *signed* result fits in a smi.
__ add(scratch2, tos, Operand(0x40000000), SetCC);
deferred->Branch(mi);
__ mov(tos, Operand(tos, LSL, kSmiTagSize));
}
}
// check that the *signed* result fits in a smi
__ add(scratch2, scratch, Operand(0x40000000), SetCC);
deferred->Branch(mi);
break;
}
case Token::SHR: {
// LSR by immediate 0 means shifting 32 bits.
if (shift_value != 0) {
__ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // Remove tag.
// LSR by immediate 0 means shifting 32 bits.
__ mov(scratch, Operand(scratch, LSR, shift_value));
if (shift_value == 1) {
// check that the *unsigned* result fits in a smi
// neither of the two high-order bits can be set:
// - 0x80000000: high bit would be lost when smi tagging
// - 0x40000000: this number would convert to negative when
// smi tagging these two cases can only happen with shifts
// by 0 or 1 when handed a valid smi
__ tst(scratch, Operand(0xc0000000));
deferred->Branch(ne);
}
__ mov(tos, Operand(scratch, LSL, kSmiTagSize));
}
// check that the *unsigned* result fits in a smi
// neither of the two high-order bits can be set:
// - 0x80000000: high bit would be lost when smi tagging
// - 0x40000000: this number would convert to negative when
// smi tagging these two cases can only happen with shifts
// by 0 or 1 when handed a valid smi
__ tst(scratch, Operand(0xc0000000));
deferred->Branch(ne);
break;
}
case Token::SAR: {
// In the ARM instructions set, ASR by immediate 0 means shifting 32
// bits.
if (shift_value != 0) {
// ASR by immediate 0 means shifting 32 bits.
__ mov(scratch, Operand(scratch, ASR, shift_value));
// Do the shift and the tag removal in one operation. If the shift
// is 31 bits (the highest possible value) then we emit the
// instruction as a shift by 0 which means shift arithmetically by
// 32.
__ mov(tos, Operand(tos, ASR, (kSmiTagSize + shift_value) & 0x1f));
// Put tag back.
__ mov(tos, Operand(tos, LSL, kSmiTagSize));
}
break;
}
default: UNREACHABLE();
}
__ mov(tos, Operand(scratch, LSL, kSmiTagSize));
deferred->BindExit();
frame_->EmitPush(tos);
break;
......
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