Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Unified Diff: runtime/vm/intermediate_language_arm.cc

Issue 252333002: Use GPRs for mints (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/intermediate_language_arm.cc
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index a44f1b5bcd44184ab77f12d5b2e492a902902d75..e5f9d8d81e53c43dc72c0a8332ccb762212b55d7 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -379,14 +379,13 @@ static Condition TokenKindToSmiCondition(Token::Kind kind) {
LocationSummary* EqualityCompareInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 2;
if (operation_cid() == kMintCid) {
- const intptr_t kNumTemps = 3;
+ const intptr_t kNumTemps = 0;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RequiresFpuRegister());
- locs->set_in(1, Location::RequiresFpuRegister());
- locs->set_temp(0, Location::RequiresFpuRegister());
- locs->set_temp(1, Location::RequiresRegister());
- locs->set_temp(2, Location::RequiresRegister());
+ locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
locs->set_out(0, Location::RequiresRegister());
return locs;
}
@@ -514,37 +513,36 @@ static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
LocationSummary* locs,
Token::Kind kind) {
ASSERT(Token::IsEqualityOperator(kind));
- QRegister left = locs->in(0).fpu_reg();
- QRegister right = locs->in(1).fpu_reg();
- QRegister tmpq = locs->temp(0).fpu_reg();
- Register tmp_lo = locs->temp(1).reg();
- Register tmp_hi = locs->temp(2).reg();
+ PairLocation* left_pair = locs->in(0).AsPairLocation();
+ Register left1 = left_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: rename to {left, right}_{lo, hi}.
Cutch 2014/05/15 18:26:08 Done.
+ Register left2 = left_pair->At(1).reg();
+ PairLocation* right_pair = locs->in(1).AsPairLocation();
+ Register right1 = right_pair->At(0).reg();
+ Register right2 = right_pair->At(1).reg();
- __ vceqqi(kWord, tmpq, left, right);
- __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(tmpq));
- // tmp_lo and tmp_hi must both be 0xffffffff.
- __ and_(tmp_lo, tmp_lo, ShifterOperand(tmp_hi));
+ Label done;
- Condition true_condition = TokenKindToMintCondition(kind);
- __ CompareImmediate(tmp_lo, 0xffffffff);
- return true_condition;
+ // Compare lower.
+ __ cmp(left1, ShifterOperand(right1));
+ __ b(&done, NE);
+ // Lower is equal, compare upper.
+ __ cmp(left2, ShifterOperand(right2));
zra 2014/05/14 18:27:41 Remove branch, instead: __ cmp(left2, ShifterOpera
Cutch 2014/05/15 18:26:08 Done but I think you meant EQ instead of NE.
zra 2014/05/15 18:30:45 Yes, you're right.
+ __ Bind(&done);
+ return TokenKindToMintCondition(kind);
}
static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
LocationSummary* locs,
Token::Kind kind) {
- QRegister left = locs->in(0).fpu_reg();
- QRegister right = locs->in(1).fpu_reg();
- DRegister dleft0 = EvenDRegisterOf(left);
- DRegister dright0 = EvenDRegisterOf(right);
- SRegister sleft0 = EvenSRegisterOf(dleft0);
- SRegister sleft1 = OddSRegisterOf(dleft0);
- SRegister sright0 = EvenSRegisterOf(dright0);
- SRegister sright1 = OddSRegisterOf(dright0);
+ PairLocation* left_pair = locs->in(0).AsPairLocation();
+ Register left1 = left_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: rename to {left, right}_{lo, hi}.
Cutch 2014/05/15 18:26:08 Done.
+ Register left2 = left_pair->At(1).reg();
+ PairLocation* right_pair = locs->in(1).AsPairLocation();
+ Register right1 = right_pair->At(0).reg();
+ Register right2 = right_pair->At(1).reg();
- Register tmp_left = locs->temp(0).reg();
- Register tmp_right = locs->temp(1).reg();
+ Register out = locs->temp(0).reg();
// 64-bit comparison
Condition hi_true_cond, hi_false_cond, lo_false_cond;
@@ -567,24 +565,23 @@ static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
}
Label is_true, is_false, done;
- __ vmovrs(tmp_left, sleft1);
- __ vmovrs(tmp_right, sright1);
- __ cmp(tmp_left, ShifterOperand(tmp_right));
+ // Compare upper halves first.
+ __ cmp(left2, ShifterOperand(right2));
__ b(&is_false, hi_false_cond);
__ b(&is_true, hi_true_cond);
zra 2014/05/14 18:27:41 Instead, to avoid so many branches: __ cmp(left2,
Cutch 2014/05/15 18:26:08 Done.
- __ vmovrs(tmp_left, sleft0);
- __ vmovrs(tmp_right, sright0);
- __ cmp(tmp_left, ShifterOperand(tmp_right));
+ // If upper is equal, compare lower half.
+ __ cmp(left1, ShifterOperand(right1));
__ b(&is_false, lo_false_cond);
+
// Else is true.
__ b(&is_true);
__ Bind(&is_false);
- __ LoadImmediate(tmp_left, 0);
+ __ LoadImmediate(out, 0);
__ b(&done);
__ Bind(&is_true);
- __ LoadImmediate(tmp_left, 1);
+ __ LoadImmediate(out, 1);
__ Bind(&done);
return NegateCondition(lo_false_cond);
}
@@ -792,13 +789,14 @@ LocationSummary* RelationalOpInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operation_cid() == kMintCid) {
- const intptr_t kNumTemps = 2;
+ const intptr_t kNumTemps = 1;
LocationSummary* locs =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RequiresFpuRegister());
- locs->set_in(1, Location::RequiresFpuRegister());
+ locs->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ locs->set_in(1, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
locs->set_temp(0, Location::RequiresRegister());
- locs->set_temp(1, Location::RequiresRegister());
locs->set_out(0, Location::RequiresRegister());
return locs;
}
@@ -1148,7 +1146,11 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
} else {
locs->set_out(0, Location::RequiresFpuRegister());
}
+ } else if (representation() == kUnboxedMint) {
+ locs->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
} else {
+ ASSERT(representation() == kTagged);
locs->set_out(0, Location::RequiresRegister());
}
return locs;
@@ -1157,7 +1159,6 @@ LocationSummary* LoadIndexedInstr::MakeLocationSummary(bool opt) const {
void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
if ((representation() == kUnboxedDouble) ||
- (representation() == kUnboxedMint) ||
(representation() == kUnboxedFloat32x4) ||
(representation() == kUnboxedInt32x4) ||
(representation() == kUnboxedFloat64x2)) {
@@ -1189,23 +1190,6 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const QRegister result = locs()->out(0).fpu_reg();
const DRegister dresult0 = EvenDRegisterOf(result);
switch (class_id()) {
- case kTypedDataInt32ArrayCid:
- __ veorq(result, result, result);
- __ ldr(TMP, element_address);
- // Re-use the index register so we don't have to require a low-numbered
- // Q register.
- // Sign-extend into idx.
- __ Asr(idx, TMP, 31);
- __ vmovdrr(dresult0, TMP, idx);
- break;
- case kTypedDataUint32ArrayCid:
- __ veorq(result, result, result);
- __ ldr(TMP, element_address);
- // Re-use the index register so we don't have to require a low-numbered
- // Q register.
- __ LoadImmediate(idx, 0);
- __ vmovdrr(dresult0, TMP, idx);
- break;
case kTypedDataFloat32ArrayCid:
// Load single precision float.
// vldrs does not support indexed addressing.
@@ -1220,6 +1204,8 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
case kTypedDataFloat32x4ArrayCid:
__ vldmd(IA, idx, dresult0, 2);
break;
+ default:
+ UNREACHABLE();
}
return;
}
@@ -1263,6 +1249,34 @@ void LoadIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
FlowGraphCompiler::DataOffsetFor(class_id()) - kHeapObjectTag);
}
element_address = Address(array, index.reg(), LSL, 0);
+
+ if (representation() == kUnboxedMint) {
+ ASSERT(locs()->out(0).IsPairLocation());
+ PairLocation* result_pair = locs()->out(0).AsPairLocation();
+ Register result1 = result_pair->At(0).reg();
+ Register result2 = result_pair->At(1).reg();
+ switch (class_id()) {
+ case kTypedDataInt32ArrayCid:
+ // Load low word.
+ __ ldr(result1, element_address);
+ // Sign extend into high word.
+ __ SignFill(result2, result1);
+ break;
+ case kTypedDataUint32ArrayCid:
+ // Load low word.
+ __ ldr(result1, element_address);
+ // Zero high word.
+ __ eor(result2, result2, ShifterOperand(result2));
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return;
+ }
+
+ ASSERT(representation() == kTagged);
+
Register result = locs()->out(0).reg();
switch (class_id()) {
case kTypedDataInt8ArrayCid:
@@ -1380,11 +1394,16 @@ LocationSummary* StoreIndexedInstr::MakeLocationSummary(bool opt) const {
break;
case kTypedDataInt32ArrayCid:
case kTypedDataUint32ArrayCid:
- // Mints are stored in Q registers. For smis, use a writable register
- // because the value must be untagged before storing.
- locs->set_in(2, value()->IsSmiValue()
- ? Location::WritableRegister()
- : Location::FpuRegisterLocation(Q7));
+ // For smis, use a writable register because the value must be untagged
+ // before storing. Mints are stored in register pairs.
+ if (value()->IsSmiValue()) {
+ locs->set_in(2, Location::WritableRegister());
+ } else {
+ // We only move the lower 32-bits so we don't care where the high bits
+ // are located.
+ locs->set_in(2, Location::Pair(Location::RequiresRegister(),
+ Location::Any()));
+ }
break;
case kTypedDataFloat32ArrayCid:
// Need low register (<= Q7).
@@ -1515,10 +1534,9 @@ void StoreIndexedInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ str(value, element_address);
} else {
ASSERT(RequiredInputRepresentation(2) == kUnboxedMint);
- QRegister value = locs()->in(2).fpu_reg();
- ASSERT(value == Q7);
- __ vmovrs(TMP, EvenSRegisterOf(EvenDRegisterOf(value)));
- __ str(TMP, element_address);
+ PairLocation* value_pair = locs()->in(2).AsPairLocation();
+ Register value1 = value_pair->At(0).reg();
+ __ str(value1, element_address);
}
break;
}
@@ -5599,20 +5617,19 @@ void CheckArrayBoundInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
Label* overflow,
- QRegister result,
- Register tmp_hi, Register tmp_lo) {
- __ vmovrrd(tmp_lo, tmp_hi, EvenDRegisterOf(result));
+ Register result_lo,
+ Register result_hi) {
// Compare upper half.
Label check_lower;
- __ CompareImmediate(tmp_hi, 0x00200000);
+ __ CompareImmediate(result_hi, 0x00200000);
__ b(overflow, GT);
__ b(&check_lower, NE);
- __ CompareImmediate(tmp_lo, 0);
+ __ CompareImmediate(result_lo, 0);
__ b(overflow, HI);
__ Bind(&check_lower);
- __ CompareImmediate(tmp_hi, -0x00200000);
+ __ CompareImmediate(result_hi, -0x00200000);
__ b(overflow, LT);
// Anything in the lower part would make the number bigger than the lower
// bound, so we are done.
@@ -5621,19 +5638,13 @@ static void EmitJavascriptIntOverflowCheck(FlowGraphCompiler* compiler,
LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 1;
- const intptr_t value_cid = value()->Type()->ToCid();
- const bool needs_writable_input = (value_cid != kMintCid);
- const bool needs_temp = (value_cid != kMintCid);
- const intptr_t kNumTemps = needs_temp ? 1 : 0;
+ const intptr_t kNumTemps = 1;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, needs_writable_input
- ? Location::WritableRegister()
- : Location::RequiresRegister());
- if (needs_temp) {
- summary->set_temp(0, Location::RequiresRegister());
- }
- summary->set_out(0, Location::RequiresFpuRegister());
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
return summary;
}
@@ -5641,19 +5652,30 @@ LocationSummary* UnboxIntegerInstr::MakeLocationSummary(bool opt) const {
void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
const intptr_t value_cid = value()->Type()->ToCid();
const Register value = locs()->in(0).reg();
- const QRegister result = locs()->out(0).fpu_reg();
+ PairLocation* result_pair = locs()->out(0).AsPairLocation();
+ Register result1 = result_pair->At(0).reg();
+ Register result2 = result_pair->At(1).reg();
+ ASSERT(value != result1);
+ ASSERT(value != result2);
__ Comment("UnboxIntegerInstr");
- __ veorq(result, result, result);
if (value_cid == kMintCid) {
- __ LoadDFromOffset(EvenDRegisterOf(result), value,
- Mint::value_offset() - kHeapObjectTag);
+ // Load low word.
+ __ LoadFromOffset(kWord,
+ result1,
+ value,
+ Mint::value_offset() - kHeapObjectTag);
+ // Load high word.
+ __ LoadFromOffset(kWord,
+ result2,
+ value,
+ Mint::value_offset() - kHeapObjectTag + kWordSize);
} else if (value_cid == kSmiCid) {
- Register temp = locs()->temp(0).reg();
- __ SmiUntag(value);
- // Sign extend value into temp.
- __ Asr(temp, value, 31);
- __ vmovdrr(EvenDRegisterOf(result), value, temp);
+ // Load Smi into result1.
+ __ mov(result1, ShifterOperand(value));
+ // Untag.
+ __ SmiUntag(result1);
+ __ SignFill(result2, result1);
} else {
Register temp = locs()->temp(0).reg();
Label* deopt = compiler->AddDeoptStub(deopt_id_,
@@ -5665,16 +5687,26 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ b(deopt, NE);
// It's a Mint.
- __ LoadDFromOffset(EvenDRegisterOf(result), value,
- Mint::value_offset() - kHeapObjectTag);
+ // Load low word.
+ __ LoadFromOffset(kWord,
+ result1,
+ value,
+ Mint::value_offset() - kHeapObjectTag);
+ // Load high word.
+ __ LoadFromOffset(kWord,
+ result2,
+ value,
+ Mint::value_offset() - kHeapObjectTag + kWordSize);
__ b(&done);
// It's a Smi.
__ Bind(&is_smi);
- __ SmiUntag(value);
- // Sign extend into temp.
- __ Asr(temp, value, 31);
- __ vmovdrr(EvenDRegisterOf(result), value, temp);
+ // Load Smi into result1.
+ __ mov(result1, ShifterOperand(value));
+ // Untag.
+ __ SmiUntag(result1);
+ // Sign extend result1 into result2.
+ __ SignFill(result2, result1);
__ Bind(&done);
}
}
@@ -5682,14 +5714,14 @@ void UnboxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
LocationSummary* BoxIntegerInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps = 2;
+ const intptr_t kNumTemps = 1;
LocationSummary* summary =
new LocationSummary(kNumInputs,
kNumTemps,
LocationSummary::kCallOnSlowPath);
- summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
summary->set_temp(0, Location::RequiresRegister());
- summary->set_temp(1, Location::RequiresRegister());
summary->set_out(0, Location::RequiresRegister());
return summary;
}
@@ -5731,40 +5763,39 @@ class BoxIntegerSlowPath : public SlowPathCode {
void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
BoxIntegerSlowPath* slow_path = new BoxIntegerSlowPath(this);
compiler->AddSlowPathCode(slow_path);
-
+ PairLocation* value_pair = locs()->in(0).AsPairLocation();
+ Register value1 = value_pair->At(0).reg();
zra 2014/05/14 18:27:41 optional: lo/hi instead of 1/2 as above
Cutch 2014/05/15 18:26:08 Done.
+ Register value2 = value_pair->At(1).reg();
+ Register tmp = locs()->temp(0).reg();
Register out_reg = locs()->out(0).reg();
- QRegister value = locs()->in(0).fpu_reg();
- DRegister dvalue0 = EvenDRegisterOf(value);
- Register lo = locs()->temp(0).reg();
- Register hi = locs()->temp(1).reg();
// Unboxed operations produce smis or mint-sized values.
// Check if value fits into a smi.
__ Comment("BoxIntegerInstr");
Label not_smi, done, maybe_pos_smi, maybe_neg_smi, is_smi;
- __ vmovrrd(lo, hi, dvalue0);
- __ CompareImmediate(hi, 0);
+ // Check high word.
zra 2014/05/14 18:27:41 Can you rewrite this to mirror the ia32 implementa
Cutch 2014/05/15 18:26:08 I took a stab at this but kept getting test failur
zra 2014/05/15 18:30:45 sgtm
+ __ CompareImmediate(value2, 0);
__ b(&maybe_pos_smi, EQ);
- __ CompareImmediate(hi, -1);
+ __ CompareImmediate(value2, -1);
__ b(&maybe_neg_smi, EQ);
__ b(&not_smi);
__ Bind(&maybe_pos_smi);
- __ CompareImmediate(lo, kSmiMax);
+ __ CompareImmediate(value1, kSmiMax);
__ b(&is_smi, LS); // unsigned lower or same.
__ b(&not_smi);
__ Bind(&maybe_neg_smi);
- __ CompareImmediate(lo, 0);
+ __ CompareImmediate(value1, 0);
__ b(&not_smi, GE);
- __ CompareImmediate(lo, kSmiMin);
+ __ CompareImmediate(value1, kSmiMin);
__ b(&not_smi, LT);
// lo is a Smi. Tag it and return.
__ Bind(&is_smi);
- __ SmiTag(lo);
- __ mov(out_reg, ShifterOperand(lo));
+ __ mov(out_reg, ShifterOperand(value1));
+ __ SmiTag(out_reg);
__ b(&done);
// Not a smi. Box it.
@@ -5773,149 +5804,178 @@ void BoxIntegerInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
Class::ZoneHandle(Isolate::Current()->object_store()->mint_class()),
slow_path->entry_label(),
out_reg,
- lo);
+ tmp);
__ Bind(slow_path->exit_label());
- __ StoreDToOffset(dvalue0, out_reg, Mint::value_offset() - kHeapObjectTag);
+ __ StoreToOffset(kWord,
+ value1,
+ out_reg,
+ Mint::value_offset() - kHeapObjectTag);
+ __ StoreToOffset(kWord,
+ value2,
+ out_reg,
+ Mint::value_offset() - kHeapObjectTag + kWordSize);
__ Bind(&done);
}
LocationSummary* BinaryMintOpInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps =
- FLAG_throw_on_javascript_int_overflow ? 2 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresFpuRegister());
- summary->set_in(1, Location::RequiresFpuRegister());
- if (FLAG_throw_on_javascript_int_overflow) {
- summary->set_temp(0, Location::RequiresRegister());
- summary->set_temp(1, Location::RequiresRegister());
- }
- if ((op_kind() == Token::kADD) || (op_kind() == Token::kSUB)) {
- // Need another temp for checking for overflow.
- summary->AddTemp(Location::RequiresFpuRegister());
- summary->AddTemp(Location::FpuRegisterLocation(Q7));
- }
- summary->set_out(0, Location::RequiresFpuRegister());
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ summary->set_in(1, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
return summary;
}
void BinaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- QRegister left = locs()->in(0).fpu_reg();
- QRegister right = locs()->in(1).fpu_reg();
- QRegister out = locs()->out(0).fpu_reg();
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left1 = left_pair->At(0).reg();
+ Register left2 = left_pair->At(1).reg();
+ PairLocation* right_pair = locs()->in(1).AsPairLocation();
+ Register right1 = right_pair->At(0).reg();
+ Register right2 = right_pair->At(1).reg();
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out1 = out_pair->At(0).reg();
+ Register out2 = out_pair->At(1).reg();
Label* deopt = NULL;
if (FLAG_throw_on_javascript_int_overflow) {
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
}
switch (op_kind()) {
- case Token::kBIT_AND: __ vandq(out, left, right); break;
- case Token::kBIT_OR: __ vorrq(out, left, right); break;
- case Token::kBIT_XOR: __ veorq(out, left, right); break;
+ case Token::kBIT_AND: {
+ __ and_(out1, left1, ShifterOperand(right1));
+ __ and_(out2, left2, ShifterOperand(right2));
+ }
+ break;
+ case Token::kBIT_OR: {
+ __ orr(out1, left1, ShifterOperand(right1));
+ __ orr(out2, left2, ShifterOperand(right2));
+ }
+ break;
+ case Token::kBIT_XOR: {
+ __ eor(out1, left1, ShifterOperand(right1));
+ __ eor(out2, left2, ShifterOperand(right2));
+ }
+ break;
case Token::kADD:
case Token::kSUB: {
- const intptr_t tmpidx = FLAG_throw_on_javascript_int_overflow ? 2 : 0;
- QRegister tmp = locs()->temp(tmpidx).fpu_reg();
- QRegister ro = locs()->temp(tmpidx + 1).fpu_reg();
- ASSERT(ro == Q7);
if (!FLAG_throw_on_javascript_int_overflow) {
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
}
if (op_kind() == Token::kADD) {
- __ vaddqi(kWordPair, out, left, right);
+ __ adds(out1, left1, ShifterOperand(right1));
+ __ adcs(out2, left2, ShifterOperand(right2));
} else {
ASSERT(op_kind() == Token::kSUB);
- __ vsubqi(kWordPair, out, left, right);
+ __ subs(out1, left1, ShifterOperand(right1));
+ __ sbcs(out2, left2, ShifterOperand(right2));
}
- __ veorq(ro, out, left);
- __ veorq(tmp, left, right);
- __ vandq(ro, tmp, ro);
- __ vmovrs(TMP, OddSRegisterOf(EvenDRegisterOf(ro)));
- // If TMP < 0, there was overflow.
- __ cmp(TMP, ShifterOperand(0));
- __ b(deopt, LT);
+ // Deopt on overflow.
+ __ b(deopt, VS);
break;
}
- default: UNREACHABLE(); break;
+ default:
+ UNREACHABLE();
+ break;
}
if (FLAG_throw_on_javascript_int_overflow) {
- Register tmp1 = locs()->temp(0).reg();
- Register tmp2 = locs()->temp(1).reg();
- EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+ EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
}
}
LocationSummary* ShiftMintOpInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 2;
- const intptr_t kNumTemps =
- FLAG_throw_on_javascript_int_overflow ? 2 : 1;
+ const intptr_t kNumTemps = 1;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
summary->set_in(1, Location::WritableRegister());
- summary->set_temp(0, Location::FpuRegisterLocation(Q7));
- if (FLAG_throw_on_javascript_int_overflow) {
- summary->set_temp(1, Location::RequiresRegister());
- }
- summary->set_out(0, Location::RequiresFpuRegister());
+ summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
return summary;
}
void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- QRegister value = locs()->in(0).fpu_reg();
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left1 = left_pair->At(0).reg();
+ Register left2 = left_pair->At(1).reg();
Register shift = locs()->in(1).reg();
- QRegister temp = locs()->temp(0).fpu_reg();
- ASSERT(temp == Q7);
- QRegister out = locs()->out(0).fpu_reg();
- DRegister dtemp0 = EvenDRegisterOf(temp);
- SRegister stemp0 = EvenSRegisterOf(dtemp0);
- SRegister stemp1 = OddSRegisterOf(dtemp0);
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out1 = out_pair->At(0).reg();
+ Register out2 = out_pair->At(1).reg();
+ Register temp = locs()->temp(0).reg();
Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
- Label done;
+ Label done, early_out;
+ // Early out if shift is 0.
__ CompareImmediate(shift, 0);
- __ vmovq(out, value);
- __ b(&done, EQ);
+ __ b(&early_out, EQ);
+
+ // Untag shift count.
__ SmiUntag(shift);
- // vshlq takes the shift value from low byte. Deopt if shift is
- // outside of [0, 63].
- __ CompareImmediate(shift, 63);
- __ b(deopt, GT);
- __ CompareImmediate(shift, 0);
+ // Deopt if shift is negative.
+ __ CompareImmediate(shift, 1);
__ b(deopt, LT);
- __ veorq(temp, temp, temp); // Zero out temp.
+ // Deopt if shift is larger than 32.
zra 2014/05/14 18:27:41 Are there funky things that happen for >= 32 as pa
Cutch 2014/05/15 18:26:08 Done.
+ __ CompareImmediate(shift, 32);
+ __ b(deopt, GT);
+
switch (op_kind()) {
case Token::kSHR: {
- __ rsb(shift, shift, ShifterOperand(0)); // Negate shift.
- __ vmovsr(stemp0, shift); // Move the shift into the low S register.
- __ vshlqi(kWordPair, out, value, temp);
+ /*
+ * Perform right shift, in pseudo C:
+ * temp = 32 - N;
+ * temp = left2 <<L temp;
+ * out1 = temp | (left1 L>> N);
+ * out2 = left2 A>> N;
+ */
+ __ rsb(temp, shift, ShifterOperand(32));
+ __ mov(temp, ShifterOperand(left2, LSL, temp));
+ __ orr(out1, temp, ShifterOperand(left1, LSR, shift));
+ __ mov(out2, ShifterOperand(left2, ASR, shift));
+ // Finished.
+ __ b(&done);
break;
}
case Token::kSHL: {
- __ vmovsr(stemp0, shift); // Move the shift into the low S register.
- __ vshlqu(kWordPair, out, value, temp);
-
- // check for overflow by shifting back and comparing.
- __ rsb(shift, shift, ShifterOperand(0));
- __ vmovsr(stemp0, shift);
- __ vshlqi(kWordPair, temp, out, temp);
- __ vceqqi(kWord, temp, temp, value);
- // Low 64 bits of temp should be all 1's, otherwise temp != value and
- // we deopt.
- __ vmovrs(shift, stemp0);
- __ CompareImmediate(shift, -1);
- __ b(deopt, NE);
- __ vmovrs(shift, stemp1);
- __ CompareImmediate(shift, -1);
+ /*
+ * Perform left shift, in pseudo C:
+ * temp = 32 - N;
+ * out2 = left2 <<L shift;
+ * out2 = out2 | (left1 L>> temp);
+ * out1 = left1 <<L shift;
+ */
+ __ rsb(temp, shift, ShifterOperand(32));
+ __ mov(out2, ShifterOperand(left2, LSL, shift));
+ __ orr(out2, out2, ShifterOperand(left1, LSR, temp));
+ __ mov(out1, ShifterOperand(left1, LSL, shift));
+
+ // Check for overflow.
+
+ // Copy high word from output.
+ __ mov(temp, ShifterOperand(out2));
+ // Shift copy right.
+ __ Asr(temp, temp, shift);
+ // Compare with high word from input.
+ __ cmp(temp, ShifterOperand(left2));
+ // Overflow if they aren't equal.
__ b(deopt, NE);
+ // Finished.
+ __ b(&done);
break;
}
default:
@@ -5923,44 +5983,50 @@ void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
break;
}
+ __ Bind(&early_out);
+ __ mov(out1, ShifterOperand(left1));
+ __ mov(out2, ShifterOperand(left2));
+
__ Bind(&done);
if (FLAG_throw_on_javascript_int_overflow) {
- Register tmp1 = locs()->in(1).reg();
- Register tmp2 = locs()->temp(1).reg();
- EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+ EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
}
}
LocationSummary* UnaryMintOpInstr::MakeLocationSummary(bool opt) const {
const intptr_t kNumInputs = 1;
- const intptr_t kNumTemps =
- FLAG_throw_on_javascript_int_overflow ? 2 : 0;
+ const intptr_t kNumTemps = 0;
LocationSummary* summary =
new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
- summary->set_in(0, Location::RequiresFpuRegister());
- summary->set_out(0, Location::RequiresFpuRegister());
- if (FLAG_throw_on_javascript_int_overflow) {
- summary->set_temp(0, Location::RequiresRegister());
- summary->set_temp(1, Location::RequiresRegister());
- }
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
return summary;
}
void UnaryMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
ASSERT(op_kind() == Token::kBIT_NOT);
- QRegister value = locs()->in(0).fpu_reg();
- QRegister out = locs()->out(0).fpu_reg();
+
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left1 = left_pair->At(0).reg();
+ Register left2 = left_pair->At(1).reg();
+
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out1 = out_pair->At(0).reg();
+ Register out2 = out_pair->At(1).reg();
+
Label* deopt = NULL;
+
if (FLAG_throw_on_javascript_int_overflow) {
deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnaryMintOp);
}
- __ vmvnq(out, value);
+ __ mvn(out1, ShifterOperand(left1));
+ __ mvn(out2, ShifterOperand(left2));
if (FLAG_throw_on_javascript_int_overflow) {
- Register tmp1 = locs()->temp(0).reg();
- Register tmp2 = locs()->temp(1).reg();
- EmitJavascriptIntOverflowCheck(compiler, deopt, out, tmp1, tmp2);
+ EmitJavascriptIntOverflowCheck(compiler, deopt, out1, out2);
}
}

Powered by Google App Engine
This is Rietveld 408576698