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

Unified Diff: runtime/vm/intermediate_language_mips.cc

Issue 777943003: Implement mint unboxing on MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years 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
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | tests/standalone/standalone.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/intermediate_language_mips.cc
===================================================================
--- runtime/vm/intermediate_language_mips.cc (revision 42125)
+++ runtime/vm/intermediate_language_mips.cc (working copy)
@@ -70,7 +70,7 @@
LocationSummary* ReturnInstr::MakeLocationSummary(Isolate* isolate,
- bool opt) const {
+ bool opt) const {
const intptr_t kNumInputs = 1;
const intptr_t kNumTemps = 0;
LocationSummary* locs = new(isolate) LocationSummary(
@@ -121,8 +121,7 @@
case GT: return LE;
case GE: return LT;
default:
- OS::Print("Error: Condition not recognized: %d\n", condition);
- UNIMPLEMENTED();
+ UNREACHABLE();
return EQ;
}
}
@@ -278,7 +277,7 @@
void LoadLocalInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
__ TraceSimMsg("LoadLocalInstr");
Register result = locs()->out(0).reg();
- __ lw(result, Address(FP, local().index() * kWordSize));
+ __ LoadFromOffset(result, FP, local().index() * kWordSize);
}
@@ -296,7 +295,7 @@
Register value = locs()->in(0).reg();
Register result = locs()->out(0).reg();
ASSERT(result == value); // Assert that register assignment is correct.
- __ sw(value, Address(FP, local().index() * kWordSize));
+ __ StoreToOffset(value, FP, local().index() * kWordSize);
}
@@ -428,12 +427,13 @@
bool opt) const {
const intptr_t kNumInputs = 2;
if (operation_cid() == kMintCid) {
- const intptr_t kNumTemps = 1;
+ const intptr_t kNumTemps = 0;
LocationSummary* locs = new(isolate) LocationSummary(
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RequiresFpuRegister());
- locs->set_in(1, Location::RequiresFpuRegister());
- locs->set_temp(0, 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;
}
@@ -553,8 +553,7 @@
static Condition EmitSmiComparisonOp(FlowGraphCompiler* compiler,
const LocationSummary& locs,
- Token::Kind kind,
- BranchLabels labels) {
+ Token::Kind kind) {
__ TraceSimMsg("EmitSmiComparisonOp");
__ Comment("EmitSmiComparisonOp");
Location left = locs.in(0);
@@ -576,6 +575,69 @@
}
+static Condition TokenKindToMintCondition(Token::Kind kind) {
+ switch (kind) {
+ case Token::kEQ: return EQ;
+ case Token::kNE: return NE;
+ case Token::kLT: return LT;
+ case Token::kGT: return GT;
+ case Token::kLTE: return LE;
+ case Token::kGTE: return GE;
+ default:
+ UNREACHABLE();
+ return VS;
+ }
+}
+
+
+static Condition EmitUnboxedMintEqualityOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind) {
+ __ TraceSimMsg("EmitUnboxedMintEqualityOp");
+ __ Comment("EmitUnboxedMintEqualityOp");
+ ASSERT(Token::IsEqualityOperator(kind));
+ PairLocation* left_pair = locs.in(0).AsPairLocation();
+ Register left_lo = left_pair->At(0).reg();
+ Register left_hi = left_pair->At(1).reg();
+ PairLocation* right_pair = locs.in(1).AsPairLocation();
+ Register right_lo = right_pair->At(0).reg();
+ Register right_hi = right_pair->At(1).reg();
+
+ __ xor_(CMPRES1, left_lo, right_lo);
+ __ xor_(CMPRES2, left_hi, right_hi);
+ __ or_(CMPRES1, CMPRES1, CMPRES2);
+ __ mov(CMPRES2, ZR);
+ return TokenKindToMintCondition(kind);
+}
+
+
+static Condition EmitUnboxedMintComparisonOp(FlowGraphCompiler* compiler,
+ const LocationSummary& locs,
+ Token::Kind kind) {
+ __ TraceSimMsg("EmitUnboxedMintComparisonOp");
+ __ Comment("EmitUnboxedMintComparisonOp");
+ PairLocation* left_pair = locs.in(0).AsPairLocation();
+ Register left_lo = left_pair->At(0).reg();
+ Register left_hi = left_pair->At(1).reg();
+ PairLocation* right_pair = locs.in(1).AsPairLocation();
+ Register right_lo = right_pair->At(0).reg();
+ Register right_hi = right_pair->At(1).reg();
+
+ Label done;
+ // Compare upper halves first.
+ __ slt(CMPRES1, left_hi, right_hi);
+ __ slt(CMPRES2, right_hi, left_hi);
+ // If higher words aren't equal, skip comparing lower words.
+ __ bne(CMPRES1, CMPRES2, &done);
+
+ __ sltu(CMPRES1, left_lo, right_lo);
+ __ sltu(CMPRES2, right_lo, left_lo);
+ __ Bind(&done);
+
+ return TokenKindToMintCondition(kind);
+}
+
+
static Condition TokenKindToDoubleCondition(Token::Kind kind) {
switch (kind) {
case Token::kEQ: return EQ;
@@ -637,7 +699,9 @@
Condition EqualityCompareInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) {
if (operation_cid() == kSmiCid) {
- return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ return EmitSmiComparisonOp(compiler, *locs(), kind());
+ } else if (operation_cid() == kMintCid) {
+ return EmitUnboxedMintEqualityOp(compiler, *locs(), kind());
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
@@ -801,13 +865,13 @@
const intptr_t kNumInputs = 2;
const intptr_t kNumTemps = 0;
if (operation_cid() == kMintCid) {
- const intptr_t kNumTemps = 2;
+ const intptr_t kNumTemps = 0;
LocationSummary* locs = new(isolate) LocationSummary(
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
- locs->set_in(0, Location::RequiresFpuRegister());
- locs->set_in(1, Location::RequiresFpuRegister());
- locs->set_temp(0, Location::RequiresRegister());
- locs->set_temp(1, 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;
}
@@ -836,7 +900,9 @@
Condition RelationalOpInstr::EmitComparisonCode(FlowGraphCompiler* compiler,
BranchLabels labels) {
if (operation_cid() == kSmiCid) {
- return EmitSmiComparisonOp(compiler, *locs(), kind(), labels);
+ return EmitSmiComparisonOp(compiler, *locs(), kind());
+ } else if (operation_cid() == kMintCid) {
+ return EmitUnboxedMintComparisonOp(compiler, *locs(), kind());
} else {
ASSERT(operation_cid() == kDoubleCid);
return EmitDoubleComparisonOp(compiler, *locs(), kind(), labels);
@@ -1196,13 +1262,16 @@
if ((representation() == kUnboxedUint32) ||
(representation() == kUnboxedInt32)) {
const Register result = locs()->out(0).reg();
+ if ((index_scale() == 1) && index.IsRegister()) {
+ __ SmiUntag(index.reg());
+ }
switch (class_id()) {
case kTypedDataInt32ArrayCid:
- ASSERT(representation() == kUnboxedUint32);
+ ASSERT(representation() == kUnboxedInt32);
__ lw(result, element_address);
break;
case kTypedDataUint32ArrayCid:
- ASSERT(representation() == kUnboxedInt32);
+ ASSERT(representation() == kUnboxedUint32);
__ lw(result, element_address);
break;
default:
@@ -1393,6 +1462,7 @@
: __ ElementAddressForIntIndex(
IsExternal(), class_id(), index_scale(),
array, Smi::Cast(index.constant()).Value());
+ ASSERT(element_address.base() != TMP); // Allowed for load only.
switch (class_id()) {
case kArrayCid:
@@ -1988,7 +2058,7 @@
__ TraceSimMsg("LoadStaticFieldInstr");
Register field = locs()->in(0).reg();
Register result = locs()->out(0).reg();
- __ lw(result, FieldAddress(field, Field::value_offset()));
+ __ LoadFromOffset(result, field, Field::value_offset() - kHeapObjectTag);
}
@@ -2577,10 +2647,10 @@
// Restore stack and initialize the two exception variables:
// exception and stack trace variables.
- __ sw(kExceptionObjectReg,
- Address(FP, exception_var().index() * kWordSize));
- __ sw(kStackTraceObjectReg,
- Address(FP, stacktrace_var().index() * kWordSize));
+ __ StoreToOffset(kExceptionObjectReg,
+ FP, exception_var().index() * kWordSize);
+ __ StoreToOffset(kStackTraceObjectReg,
+ FP, stacktrace_var().index() * kWordSize);
}
@@ -3156,7 +3226,12 @@
LocationSummary* summary = new(isolate) LocationSummary(
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
summary->set_in(0, Location::RequiresRegister());
- summary->set_out(0, Location::RequiresFpuRegister());
+ if (representation() == kUnboxedMint) {
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ } else {
+ summary->set_out(0, Location::RequiresFpuRegister());
+ }
return summary;
}
@@ -3166,7 +3241,13 @@
switch (representation()) {
case kUnboxedMint: {
- UNIMPLEMENTED();
+ PairLocation* result = locs()->out(0).AsPairLocation();
+ __ LoadFromOffset(result->At(0).reg(),
+ box,
+ ValueOffset() - kHeapObjectTag);
+ __ LoadFromOffset(result->At(1).reg(),
+ box,
+ ValueOffset() - kHeapObjectTag + kWordSize);
break;
}
@@ -3195,7 +3276,9 @@
switch (representation()) {
case kUnboxedMint: {
- UNIMPLEMENTED();
+ PairLocation* result = locs()->out(0).AsPairLocation();
+ __ SmiUntag(result->At(0).reg(), box);
+ __ sra(result->At(1).reg(), result->At(0).reg(), 31);
break;
}
@@ -3271,10 +3354,10 @@
Register out = locs()->out(0).reg();
ASSERT(value != out);
- Label done;
__ SmiTag(out, value);
if (!ValueFitsSmi()) {
Register temp = locs()->temp(0).reg();
+ Label done;
if (from_representation() == kUnboxedInt32) {
__ SmiUntag(CMPRES1, out);
__ BranchEqual(CMPRES1, value, &done);
@@ -3308,8 +3391,63 @@
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(BoxInt64Instr);
+LocationSummary* BoxInt64Instr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = ValueFitsSmi() ? 0 : 1;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate,
+ kNumInputs,
+ kNumTemps,
+ ValueFitsSmi() ? LocationSummary::kNoCall
+ : LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ if (!ValueFitsSmi()) {
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+void BoxInt64Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ if (ValueFitsSmi()) {
+ PairLocation* value_pair = locs()->in(0).AsPairLocation();
+ Register value_lo = value_pair->At(0).reg();
+ Register out_reg = locs()->out(0).reg();
+ __ SmiTag(out_reg, value_lo);
+ return;
+ }
+
+ PairLocation* value_pair = locs()->in(0).AsPairLocation();
+ Register value_lo = value_pair->At(0).reg();
+ Register value_hi = value_pair->At(1).reg();
+ Register tmp = locs()->temp(0).reg();
+ Register out_reg = locs()->out(0).reg();
+
+ Label not_smi, done;
+ __ SmiTag(out_reg, value_lo);
+ __ SmiUntag(tmp, out_reg);
+ __ bne(tmp, value_lo, &not_smi);
+ __ delay_slot()->sra(tmp, out_reg, 31);
+ __ beq(tmp, value_hi, &done);
+
+ __ Bind(&not_smi);
+ BoxAllocationSlowPath::Allocate(
+ compiler,
+ this,
+ compiler->mint_class(),
+ out_reg,
+ tmp);
+ __ StoreToOffset(value_lo, out_reg, Mint::value_offset() - kHeapObjectTag);
+ __ StoreToOffset(value_hi,
+ out_reg,
+ Mint::value_offset() - kHeapObjectTag + kWordSize);
+ __ Bind(&done);
+}
+
+
LocationSummary* UnboxInteger32Instr::MakeLocationSummary(Isolate* isolate,
bool opt) const {
ASSERT((representation() == kUnboxedInt32) ||
@@ -4453,7 +4591,7 @@
}
// Load receiver into T0.
- __ lw(T0, Address(SP, (instance_call()->ArgumentCount() - 1) * kWordSize));
+ __ LoadFromOffset(T0, SP, (instance_call()->ArgumentCount() - 1) * kWordSize);
Label* deopt = compiler->AddDeoptStub(
deopt_id(), ICData::kDeoptPolymorphicInstanceCallTestFail);
@@ -4657,16 +4795,301 @@
}
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryMintOpInstr);
+LocationSummary* BinaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ 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) {
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left_lo = left_pair->At(0).reg();
+ Register left_hi = left_pair->At(1).reg();
+ PairLocation* right_pair = locs()->in(1).AsPairLocation();
+ Register right_lo = right_pair->At(0).reg();
+ Register right_hi = right_pair->At(1).reg();
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out_lo = out_pair->At(0).reg();
+ Register out_hi = out_pair->At(1).reg();
+
+ Label* deopt = NULL;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptBinaryMintOp);
+ }
+ switch (op_kind()) {
+ case Token::kBIT_AND: {
+ __ and_(out_lo, left_lo, right_lo);
+ __ and_(out_hi, left_hi, right_hi);
+ break;
+ }
+ case Token::kBIT_OR: {
+ __ or_(out_lo, left_lo, right_lo);
+ __ or_(out_hi, left_hi, right_hi);
+ break;
+ }
+ case Token::kBIT_XOR: {
+ __ xor_(out_lo, left_lo, right_lo);
+ __ xor_(out_hi, left_hi, right_hi);
+ break;
+ }
+ case Token::kADD:
+ case Token::kSUB: {
+ if (op_kind() == Token::kADD) {
+ __ addu(out_lo, left_lo, right_lo);
+ __ sltu(TMP, out_lo, left_lo); // TMP = carry of left_lo + right_lo.
+ __ addu(out_hi, left_hi, right_hi);
+ __ addu(out_hi, out_hi, TMP);
+ if (can_overflow()) {
+ __ xor_(CMPRES1, out_hi, left_hi);
+ __ xor_(TMP, out_hi, right_hi);
+ __ and_(CMPRES1, TMP, CMPRES1);
+ __ bltz(CMPRES1, deopt);
+ }
+ } else {
+ __ subu(out_lo, left_lo, right_lo);
+ __ sltu(TMP, left_lo, out_lo); // TMP = borrow of left_lo - right_lo.
+ __ subu(out_hi, left_hi, right_hi);
+ __ subu(out_hi, out_hi, TMP);
+ if (can_overflow()) {
+ __ xor_(CMPRES1, out_hi, left_hi);
+ __ xor_(TMP, left_hi, right_hi);
+ __ and_(CMPRES1, TMP, CMPRES1);
+ __ bltz(CMPRES1, deopt);
+ }
+ }
+ break;
+ }
+ case Token::kMUL: {
+ // The product of two signed 32-bit integers fits in a signed 64-bit
+ // result without causing overflow.
+ // We deopt on larger inputs.
+ // TODO(regis): Range analysis may eliminate the deopt check.
+ __ sra(CMPRES1, left_lo, 31);
+ __ bne(CMPRES1, left_hi, deopt);
+ __ delay_slot()->sra(CMPRES2, right_lo, 31);
+ __ bne(CMPRES2, right_hi, deopt);
+ __ delay_slot()->mult(left_lo, right_lo);
+ __ mflo(out_lo);
+ __ mfhi(out_hi);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+LocationSummary* ShiftMintOpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ summary->set_in(1, Location::WritableRegisterOrSmiConstant(right()));
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ return summary;
+}
+
+
+static const intptr_t kMintShiftCountLimit = 63;
+
bool ShiftMintOpInstr::has_shift_count_check() const {
- UNREACHABLE();
- return false;
+ return !RangeUtils::IsWithin(
+ right()->definition()->range(), 0, kMintShiftCountLimit);
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftMintOpInstr);
-DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryMintOpInstr);
+void ShiftMintOpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left_lo = left_pair->At(0).reg();
+ Register left_hi = left_pair->At(1).reg();
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out_lo = out_pair->At(0).reg();
+ Register out_hi = out_pair->At(1).reg();
+
+ Label* deopt = NULL;
+ if (CanDeoptimize()) {
+ deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
+ }
+ if (locs()->in(1).IsConstant()) {
+ // Code for a constant shift amount.
+ ASSERT(locs()->in(1).constant().IsSmi());
+ const int32_t shift =
+ reinterpret_cast<int32_t>(locs()->in(1).constant().raw()) >> 1;
+ switch (op_kind()) {
+ case Token::kSHR: {
+ if (shift < 32) {
+ __ sll(out_lo, left_hi, 32 - shift);
+ __ srl(TMP, left_lo, shift);
+ __ or_(out_lo, out_lo, TMP);
+ __ sra(out_hi, left_hi, shift);
+ } else {
+ __ sra(out_lo, left_hi, shift - 32);
+ __ sra(out_hi, left_hi, 31);
+ }
+ break;
+ }
+ case Token::kSHL: {
+ if (shift < 32) {
+ __ srl(out_hi, left_lo, 32 - shift);
+ __ sll(TMP, left_hi, shift);
+ __ or_(out_hi, out_hi, TMP);
+ __ sll(out_lo, left_lo, shift);
+ } else {
+ __ sll(out_hi, left_lo, shift - 32);
+ __ mov(out_lo, ZR);
+ }
+ // Check for overflow.
+ if (can_overflow()) {
+ // Compare high word from input with shifted high word from output.
+ // Overflow if they aren't equal.
+ // If shift > 32, also compare low word from input with high word from
+ // output shifted back shift - 32.
+ if (shift > 32) {
+ __ sra(TMP, out_hi, shift - 32);
+ __ bne(left_lo, TMP, deopt);
+ __ delay_slot()->sra(TMP, out_hi, 31);
+ } else if (shift == 32) {
+ __ sra(TMP, out_hi, 31);
+ } else {
+ __ sra(TMP, out_hi, shift);
+ }
+ __ bne(left_hi, TMP, deopt);
+ }
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ } else {
+ // Code for a variable shift amount.
+ Register shift = locs()->in(1).reg();
+
+ // Deopt if shift is larger than 63 or less than 0.
+ if (has_shift_count_check()) {
+ __ sltiu(CMPRES1, shift, Immediate(2*(kMintShiftCountLimit + 1)));
+ __ beq(CMPRES1, ZR, deopt);
+ // Untag shift count.
+ __ delay_slot()->SmiUntag(shift);
+ } else {
+ // Untag shift count.
+ __ SmiUntag(shift);
+ }
+
+ switch (op_kind()) {
+ case Token::kSHR: {
+ Label large_shift, done;
+ __ sltiu(CMPRES1, shift, Immediate(32));
+ __ beq(CMPRES1, ZR, &large_shift);
+
+ // shift < 32.
+ __ delay_slot()->ori(TMP, ZR, Immediate(32));
+ __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31.
+ __ sllv(out_lo, left_hi, TMP);
+ __ srlv(TMP, left_lo, shift);
+ __ or_(out_lo, out_lo, TMP);
+ __ b(&done);
+ __ delay_slot()->srav(out_hi, left_hi, shift);
+
+ // shift >= 32.
+ __ Bind(&large_shift);
+ __ sra(out_hi, left_hi, 31);
+ __ srav(out_lo, left_hi, shift); // Only 5 low bits of shift used.
+
+ __ Bind(&done);
+ break;
+ }
+ case Token::kSHL: {
+ Label large_shift, done;
+ __ sltiu(CMPRES1, shift, Immediate(32));
+ __ beq(CMPRES1, ZR, &large_shift);
+
+ // shift < 32.
+ __ delay_slot()->ori(TMP, ZR, Immediate(32));
+ __ subu(TMP, TMP, shift); // TMP = 32 - shift; 0 < TMP <= 31.
+ __ srlv(out_hi, left_lo, TMP);
+ __ sllv(TMP, left_hi, shift);
+ __ or_(out_hi, out_hi, TMP);
+ // Check for overflow.
+ if (can_overflow()) {
+ // Compare high word from input with shifted high word from output.
+ __ srav(TMP, out_hi, shift);
+ __ beq(TMP, left_hi, &done);
+ __ delay_slot()->sllv(out_lo, left_lo, shift);
+ __ b(deopt);
+ } else {
+ __ b(&done);
+ __ delay_slot()->sllv(out_lo, left_lo, shift);
+ }
+
+ // shift >= 32.
+ __ Bind(&large_shift);
+ __ sllv(out_hi, left_lo, shift); // Only 5 low bits of shift used.
+ // Check for overflow.
+ if (can_overflow()) {
+ // Compare low word from input with shifted high word from output and
+ // high word from input to sign of output.
+ // Overflow if they aren't equal.
+ __ srav(TMP, out_hi, shift);
+ __ bne(TMP, left_lo, deopt);
+ __ delay_slot()->sra(TMP, out_hi, 31);
+ __ bne(TMP, left_hi, deopt);
+ __ delay_slot()->mov(out_lo, ZR);
+ } else {
+ __ mov(out_lo, ZR);
+ }
+ __ Bind(&done);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+
+LocationSummary* UnaryMintOpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ 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);
+ PairLocation* left_pair = locs()->in(0).AsPairLocation();
+ Register left_lo = left_pair->At(0).reg();
+ Register left_hi = left_pair->At(1).reg();
+
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out_lo = out_pair->At(0).reg();
+ Register out_hi = out_pair->At(1).reg();
+
+ __ nor(out_lo, ZR, left_lo);
+ __ nor(out_hi, ZR, left_hi);
+}
+
+
CompileType BinaryUint32OpInstr::ComputeType() const {
return CompileType::Int();
}
@@ -4682,9 +5105,142 @@
}
-DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryUint32OpInstr)
-DEFINE_UNIMPLEMENTED_INSTRUCTION(ShiftUint32OpInstr)
-DEFINE_UNIMPLEMENTED_INSTRUCTION(UnaryUint32OpInstr)
+LocationSummary* BinaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+
+void BinaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register left = locs()->in(0).reg();
+ Register right = locs()->in(1).reg();
+ Register out = locs()->out(0).reg();
+ ASSERT(out != left);
+ switch (op_kind()) {
+ case Token::kBIT_AND:
+ __ and_(out, left, right);
+ break;
+ case Token::kBIT_OR:
+ __ or_(out, left, right);
+ break;
+ case Token::kBIT_XOR:
+ __ xor_(out, left, right);
+ break;
+ case Token::kADD:
+ __ addu(out, left, right);
+ break;
+ case Token::kSUB:
+ __ subu(out, left, right);
+ break;
+ case Token::kMUL:
+ __ multu(left, right);
+ __ mflo(out);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+LocationSummary* ShiftUint32OpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 1;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_in(1, Location::RegisterOrSmiConstant(right()));
+ summary->set_temp(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+
+void ShiftUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ const intptr_t kShifterLimit = 31;
+
+ Register left = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+ Register temp = locs()->temp(0).reg();
+
+ ASSERT(left != out);
+
+ Label* deopt = compiler->AddDeoptStub(deopt_id(), ICData::kDeoptShiftMintOp);
+
+ if (locs()->in(1).IsConstant()) {
+ // Shifter is constant.
+
+ const Object& constant = locs()->in(1).constant();
+ ASSERT(constant.IsSmi());
+ const intptr_t shift_value = Smi::Cast(constant).Value();
+
+ // Do the shift: (shift_value > 0) && (shift_value <= kShifterLimit).
+ switch (op_kind()) {
+ case Token::kSHR:
+ __ srl(out, left, shift_value);
+ break;
+ case Token::kSHL:
+ __ sll(out, left, shift_value);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ return;
+ }
+
+ // Non constant shift value.
+ Register shifter = locs()->in(1).reg();
+
+ __ SmiUntag(temp, shifter);
+ // If shift value is < 0, deoptimize.
+ __ bltz(temp, deopt);
+ __ delay_slot()->mov(out, left);
+ __ sltiu(CMPRES1, temp, Immediate(kShifterLimit + 1));
+ __ movz(out, ZR, CMPRES1); // out = shift > kShifterLimit ? 0 : left.
+ // Do the shift % 32.
+ switch (op_kind()) {
+ case Token::kSHR:
+ __ srlv(out, out, temp);
+ break;
+ case Token::kSHL:
+ __ sllv(out, out, temp);
+ break;
+ default:
+ UNREACHABLE();
+ }
+}
+
+
+LocationSummary* UnaryUint32OpInstr::MakeLocationSummary(Isolate* isolate,
+ bool opt) const {
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary = new(isolate) LocationSummary(
+ isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::RequiresRegister());
+ return summary;
+}
+
+
+void UnaryUint32OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+ Register left = locs()->in(0).reg();
+ Register out = locs()->out(0).reg();
+ ASSERT(left != out);
+
+ ASSERT(op_kind() == Token::kBIT_NOT);
+
+ __ nor(out, ZR, left);
+}
+
+
DEFINE_UNIMPLEMENTED_INSTRUCTION(BinaryInt32OpInstr)
@@ -4695,9 +5251,15 @@
LocationSummary* summary = new(isolate) LocationSummary(
isolate, kNumInputs, kNumTemps, LocationSummary::kNoCall);
if (from() == kUnboxedMint) {
- UNREACHABLE();
+ ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
+ summary->set_in(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
+ summary->set_out(0, Location::RequiresRegister());
} else if (to() == kUnboxedMint) {
- UNREACHABLE();
+ ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
+ summary->set_in(0, Location::RequiresRegister());
+ summary->set_out(0, Location::Pair(Location::RequiresRegister(),
+ Location::RequiresRegister()));
} else {
ASSERT((to() == kUnboxedUint32) || (to() == kUnboxedInt32));
ASSERT((from() == kUnboxedUint32) || (from() == kUnboxedInt32));
@@ -4723,10 +5285,34 @@
__ BranchSignedLess(out, Immediate(0), deopt);
}
} else if (from() == kUnboxedMint) {
- UNREACHABLE();
- } else if (to() == kUnboxedMint) {
- ASSERT(from() == kUnboxedUint32 || from() == kUnboxedInt32);
- UNREACHABLE();
+ ASSERT(to() == kUnboxedUint32 || to() == kUnboxedInt32);
+ PairLocation* in_pair = locs()->in(0).AsPairLocation();
+ Register in_lo = in_pair->At(0).reg();
+ Register in_hi = in_pair->At(1).reg();
+ Register out = locs()->out(0).reg();
+ // Copy low word.
+ __ mov(out, in_lo);
+ if (CanDeoptimize()) {
+ Label* deopt =
+ compiler->AddDeoptStub(deopt_id(), ICData::kDeoptUnboxInteger);
+ ASSERT(to() == kUnboxedInt32);
+ __ sra(TMP, in_lo, 31);
+ __ bne(in_hi, TMP, deopt);
+ }
+ } else if (from() == kUnboxedUint32 || from() == kUnboxedInt32) {
+ ASSERT(to() == kUnboxedMint);
+ Register in = locs()->in(0).reg();
+ PairLocation* out_pair = locs()->out(0).AsPairLocation();
+ Register out_lo = out_pair->At(0).reg();
+ Register out_hi = out_pair->At(1).reg();
+ // Copy low word.
+ __ mov(out_lo, in);
+ if (from() == kUnboxedUint32) {
+ __ xor_(out_hi, out_hi, out_hi);
+ } else {
+ ASSERT(from() == kUnboxedInt32);
+ __ sra(out_hi, in, 31);
+ }
} else {
UNREACHABLE();
}
« no previous file with comments | « runtime/vm/intermediate_language_arm.cc ('k') | tests/standalone/standalone.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698