X64 Crankshaft: Add ModI and ModT to x64 optimizing compiler.
Review URL: http://codereview.chromium.org/6548005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ea0dda89bb
commit
e1448ebd34
@ -683,7 +683,42 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
|
||||
|
||||
|
||||
void LCodeGen::DoModI(LModI* instr) {
|
||||
Abort("Unimplemented: %s", "DoModI");
|
||||
LOperand* right = instr->InputAt(1);
|
||||
ASSERT(ToRegister(instr->result()).is(rdx));
|
||||
ASSERT(ToRegister(instr->InputAt(0)).is(rax));
|
||||
ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
|
||||
ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
|
||||
|
||||
Register right_reg = ToRegister(right);
|
||||
|
||||
// Check for x % 0.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
|
||||
__ testl(right_reg, right_reg);
|
||||
DeoptimizeIf(zero, instr->environment());
|
||||
}
|
||||
|
||||
// Sign extend eax to edx. (We are using only the low 32 bits of the values.)
|
||||
__ cdq();
|
||||
|
||||
// Check for (0 % -x) that will produce negative zero.
|
||||
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
|
||||
NearLabel positive_left;
|
||||
NearLabel done;
|
||||
__ testl(rax, rax);
|
||||
__ j(not_sign, &positive_left);
|
||||
__ idivl(right_reg);
|
||||
|
||||
// Test the remainder for 0, because then the result would be -0.
|
||||
__ testl(rdx, rdx);
|
||||
__ j(not_zero, &done);
|
||||
|
||||
DeoptimizeIf(no_condition, instr->environment());
|
||||
__ bind(&positive_left);
|
||||
__ idivl(right_reg);
|
||||
__ bind(&done);
|
||||
} else {
|
||||
__ idivl(right_reg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1318,8 +1318,32 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
|
||||
|
||||
|
||||
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
|
||||
Abort("Unimplemented: %s", "DoMod");
|
||||
return NULL;
|
||||
if (instr->representation().IsInteger32()) {
|
||||
ASSERT(instr->left()->representation().IsInteger32());
|
||||
ASSERT(instr->right()->representation().IsInteger32());
|
||||
// The temporary operand is necessary to ensure that right is not allocated
|
||||
// into edx.
|
||||
LOperand* temp = FixedTemp(rdx);
|
||||
LOperand* value = UseFixed(instr->left(), rax);
|
||||
LOperand* divisor = UseRegister(instr->right());
|
||||
LModI* mod = new LModI(value, divisor, temp);
|
||||
LInstruction* result = DefineFixed(mod, rdx);
|
||||
return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
|
||||
instr->CheckFlag(HValue::kCanBeDivByZero))
|
||||
? AssignEnvironment(result)
|
||||
: result;
|
||||
} else if (instr->representation().IsTagged()) {
|
||||
return DoArithmeticT(Token::MOD, instr);
|
||||
} else {
|
||||
ASSERT(instr->representation().IsDouble());
|
||||
// We call a C function for double modulo. It can't trigger a GC.
|
||||
// We need to use fixed result register for the call.
|
||||
// TODO(fschneider): Allow any register as input registers.
|
||||
LOperand* left = UseFixedDouble(instr->left(), xmm1);
|
||||
LOperand* right = UseFixedDouble(instr->right(), xmm2);
|
||||
LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
|
||||
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user