X64 Crankshaft: Add bit operations and shifts to x64 crankshaft.

Review URL: http://codereview.chromium.org/6246099

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6632 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2011-02-04 11:10:39 +00:00
parent 8d4e0bb39c
commit c5de2c95fa
3 changed files with 211 additions and 22 deletions

View File

@ -894,6 +894,10 @@ class Assembler : public Malloced {
arithmetic_op(0x0B, dst, src);
}
void orl(Register dst, const Operand& src) {
arithmetic_op_32(0x0B, dst, src);
}
void or_(const Operand& dst, Register src) {
arithmetic_op(0x09, src, dst);
}
@ -1057,6 +1061,18 @@ class Assembler : public Malloced {
arithmetic_op_32(0x33, dst, src);
}
void xorl(Register dst, const Operand& src) {
arithmetic_op_32(0x33, dst, src);
}
void xorl(Register dst, Immediate src) {
immediate_arithmetic_op_32(0x6, dst, src);
}
void xorl(const Operand& dst, Immediate src) {
immediate_arithmetic_op_32(0x6, dst, src);
}
void xor_(Register dst, const Operand& src) {
arithmetic_op(0x33, dst, src);
}

View File

@ -605,11 +605,115 @@ void LCodeGen::DoMulI(LMulI* instr) {
void LCodeGen::DoBitI(LBitI* instr) {
Abort("Unimplemented: %s", "DoBitI");}
LOperand* left = instr->InputAt(0);
LOperand* right = instr->InputAt(1);
ASSERT(left->Equals(instr->result()));
ASSERT(left->IsRegister());
if (right->IsConstantOperand()) {
int right_operand = ToInteger32(LConstantOperand::cast(right));
switch (instr->op()) {
case Token::BIT_AND:
__ andl(ToRegister(left), Immediate(right_operand));
break;
case Token::BIT_OR:
__ orl(ToRegister(left), Immediate(right_operand));
break;
case Token::BIT_XOR:
__ xorl(ToRegister(left), Immediate(right_operand));
break;
default:
UNREACHABLE();
break;
}
} else if (right->IsStackSlot()) {
switch (instr->op()) {
case Token::BIT_AND:
__ andl(ToRegister(left), ToOperand(right));
break;
case Token::BIT_OR:
__ orl(ToRegister(left), ToOperand(right));
break;
case Token::BIT_XOR:
__ xorl(ToRegister(left), ToOperand(right));
break;
default:
UNREACHABLE();
break;
}
} else {
ASSERT(right->IsRegister());
switch (instr->op()) {
case Token::BIT_AND:
__ andl(ToRegister(left), ToRegister(right));
break;
case Token::BIT_OR:
__ orl(ToRegister(left), ToRegister(right));
break;
case Token::BIT_XOR:
__ xorl(ToRegister(left), ToRegister(right));
break;
default:
UNREACHABLE();
break;
}
}
}
void LCodeGen::DoShiftI(LShiftI* instr) {
Abort("Unimplemented: %s", "DoShiftI");
LOperand* left = instr->InputAt(0);
LOperand* right = instr->InputAt(1);
ASSERT(left->Equals(instr->result()));
ASSERT(left->IsRegister());
if (right->IsRegister()) {
ASSERT(ToRegister(right).is(rcx));
switch (instr->op()) {
case Token::SAR:
__ sarl_cl(ToRegister(left));
break;
case Token::SHR:
__ shrl_cl(ToRegister(left));
if (instr->can_deopt()) {
__ testl(ToRegister(left), ToRegister(left));
DeoptimizeIf(negative, instr->environment());
}
break;
case Token::SHL:
__ shll_cl(ToRegister(left));
break;
default:
UNREACHABLE();
break;
}
} else {
int value = ToInteger32(LConstantOperand::cast(right));
uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
switch (instr->op()) {
case Token::SAR:
if (shift_count != 0) {
__ sarl(ToRegister(left), Immediate(shift_count));
}
break;
case Token::SHR:
if (shift_count == 0 && instr->can_deopt()) {
__ testl(ToRegister(left), ToRegister(left));
DeoptimizeIf(negative, instr->environment());
} else {
__ shrl(ToRegister(left), Immediate(shift_count));
}
break;
case Token::SHL:
if (shift_count != 0) {
__ shll(ToRegister(left), Immediate(shift_count));
}
break;
default:
UNREACHABLE();
break;
}
}
}
@ -686,7 +790,9 @@ void LCodeGen::DoValueOf(LValueOf* instr) {
void LCodeGen::DoBitNotI(LBitNotI* instr) {
Abort("Unimplemented: %s", "DoBitNotI");
LOperand* input = instr->InputAt(0);
ASSERT(input->Equals(instr->result()));
__ not_(ToRegister(input));
}

View File

@ -162,6 +162,12 @@ const char* LArithmeticT::Mnemonic() const {
case Token::MUL: return "mul-t";
case Token::MOD: return "mod-t";
case Token::DIV: return "div-t";
case Token::BIT_AND: return "bit-and-t";
case Token::BIT_OR: return "bit-or-t";
case Token::BIT_XOR: return "bit-xor-t";
case Token::SHL: return "sal-t";
case Token::SAR: return "sar-t";
case Token::SHR: return "shr-t";
default:
UNREACHABLE();
return NULL;
@ -741,8 +747,72 @@ LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) {
LInstruction* LChunkBuilder::DoBit(Token::Value op,
HBitwiseBinaryOperation* instr) {
Abort("Unimplemented: %s", "DoBit");
return NULL;
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand());
return DefineSameAsFirst(new LBitI(op, left, right));
} else {
ASSERT(instr->representation().IsTagged());
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
LArithmeticT* result = new LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
}
LInstruction* LChunkBuilder::DoShift(Token::Value op,
HBitwiseBinaryOperation* instr) {
if (instr->representation().IsTagged()) {
ASSERT(instr->left()->representation().IsTagged());
ASSERT(instr->right()->representation().IsTagged());
LOperand* left = UseFixed(instr->left(), rdx);
LOperand* right = UseFixed(instr->right(), rax);
LArithmeticT* result = new LArithmeticT(op, left, right);
return MarkAsCall(DefineFixed(result, rax), instr);
}
ASSERT(instr->representation().IsInteger32());
ASSERT(instr->OperandAt(0)->representation().IsInteger32());
ASSERT(instr->OperandAt(1)->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->OperandAt(0));
HValue* right_value = instr->OperandAt(1);
LOperand* right = NULL;
int constant_value = 0;
if (right_value->IsConstant()) {
HConstant* constant = HConstant::cast(right_value);
right = chunk_->DefineConstantOperand(constant);
constant_value = constant->Integer32Value() & 0x1f;
} else {
right = UseFixed(right_value, rcx);
}
// Shift operations can only deoptimize if we do a logical shift
// by 0 and the result cannot be truncated to int32.
bool can_deopt = (op == Token::SHR && constant_value == 0);
if (can_deopt) {
bool can_truncate = true;
for (int i = 0; i < instr->uses()->length(); i++) {
if (!instr->uses()->at(i)->CheckFlag(HValue::kTruncatingToInt32)) {
can_truncate = false;
break;
}
}
can_deopt = !can_truncate;
}
LShiftI* result = new LShiftI(op, left, right, can_deopt);
return can_deopt
? AssignEnvironment(DefineSameAsFirst(result))
: DefineSameAsFirst(result);
}
@ -1131,44 +1201,41 @@ LInstruction* LChunkBuilder::DoCallRuntime(HCallRuntime* instr) {
LInstruction* LChunkBuilder::DoShr(HShr* instr) {
Abort("Unimplemented: %s", "DoShr");
return NULL;
return DoShift(Token::SHR, instr);
}
LInstruction* LChunkBuilder::DoSar(HSar* instr) {
Abort("Unimplemented: %s", "DoSar");
return NULL;
return DoShift(Token::SAR, instr);
}
LInstruction* LChunkBuilder::DoShl(HShl* instr) {
Abort("Unimplemented: %s", "DoShl");
return NULL;
return DoShift(Token::SHL, instr);
}
LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) {
Abort("Unimplemented: %s", "DoBitAnd");
return NULL;
return DoBit(Token::BIT_AND, instr);
}
LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) {
Abort("Unimplemented: %s", "DoBitNot");
return NULL;
ASSERT(instr->value()->representation().IsInteger32());
ASSERT(instr->representation().IsInteger32());
LOperand* input = UseRegisterAtStart(instr->value());
LBitNotI* result = new LBitNotI(input);
return DefineSameAsFirst(result);
}
LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) {
Abort("Unimplemented: %s", "DoBitOr");
return NULL;
return DoBit(Token::BIT_OR, instr);
}
LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
Abort("Unimplemented: %s", "DoBitXor");
return NULL;
return DoBit(Token::BIT_XOR, instr);
}