Revert "Revert "Upgrade to 5.0.71.48""
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc
index 9b074b0..bdf4c47 100644
--- a/src/compiler/arm/code-generator-arm.cc
+++ b/src/compiler/arm/code-generator-arm.cc
@@ -206,6 +206,19 @@
: OutOfLineCode(gen),
object_(object),
index_(index),
+ index_immediate_(0),
+ value_(value),
+ scratch0_(scratch0),
+ scratch1_(scratch1),
+ mode_(mode) {}
+
+ OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index,
+ Register value, Register scratch0, Register scratch1,
+ RecordWriteMode mode)
+ : OutOfLineCode(gen),
+ object_(object),
+ index_(no_reg),
+ index_immediate_(index),
value_(value),
scratch0_(scratch0),
scratch1_(scratch1),
@@ -215,24 +228,36 @@
if (mode_ > RecordWriteMode::kValueIsPointer) {
__ JumpIfSmi(value_, exit());
}
- if (mode_ > RecordWriteMode::kValueIsMap) {
- __ CheckPageFlag(value_, scratch0_,
- MemoryChunk::kPointersToHereAreInterestingMask, eq,
- exit());
- }
+ __ CheckPageFlag(value_, scratch0_,
+ MemoryChunk::kPointersToHereAreInterestingMask, eq,
+ exit());
+ RememberedSetAction const remembered_set_action =
+ mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
+ : OMIT_REMEMBERED_SET;
SaveFPRegsMode const save_fp_mode =
frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
- // TODO(turbofan): Once we get frame elision working, we need to save
- // and restore lr properly here if the frame was elided.
+ if (!frame()->needs_frame()) {
+ // We need to save and restore lr if the frame was elided.
+ __ Push(lr);
+ }
RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
- EMIT_REMEMBERED_SET, save_fp_mode);
- __ add(scratch1_, object_, index_);
+ remembered_set_action, save_fp_mode);
+ if (index_.is(no_reg)) {
+ __ add(scratch1_, object_, Operand(index_immediate_));
+ } else {
+ DCHECK_EQ(0, index_immediate_);
+ __ add(scratch1_, object_, Operand(index_));
+ }
__ CallStub(&stub);
+ if (!frame()->needs_frame()) {
+ __ Pop(lr);
+ }
}
private:
Register const object_;
Register const index_;
+ int32_t const index_immediate_; // Valid if index_.is(no_reg).
Register const value_;
Register const scratch0_;
Register const scratch1_;
@@ -449,11 +474,6 @@
frame_access_state()->ClearSPDelta();
break;
}
- case kArchLazyBailout: {
- EnsureSpaceForLazyDeopt();
- RecordCallPosition(instr);
- break;
- }
case kArchPrepareCallCFunction: {
int const num_parameters = MiscField::decode(instr->opcode());
__ PrepareCallCFunction(num_parameters, kScratchReg);
@@ -514,6 +534,13 @@
__ mov(i.OutputRegister(), fp);
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
+ case kArchParentFramePointer:
+ if (frame_access_state()->frame()->needs_frame()) {
+ __ ldr(i.OutputRegister(), MemOperand(fp, 0));
+ } else {
+ __ mov(i.OutputRegister(), fp);
+ }
+ break;
case kArchTruncateDoubleToI:
__ TruncateDoubleToI(i.OutputRegister(), i.InputFloat64Register(0));
DCHECK_EQ(LeaveCC, i.OutputSBit());
@@ -522,19 +549,43 @@
RecordWriteMode mode =
static_cast<RecordWriteMode>(MiscField::decode(instr->opcode()));
Register object = i.InputRegister(0);
- Register index = i.InputRegister(1);
Register value = i.InputRegister(2);
Register scratch0 = i.TempRegister(0);
Register scratch1 = i.TempRegister(1);
- auto ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
- scratch0, scratch1, mode);
- __ str(value, MemOperand(object, index));
+ OutOfLineRecordWrite* ool;
+
+ AddressingMode addressing_mode =
+ AddressingModeField::decode(instr->opcode());
+ if (addressing_mode == kMode_Offset_RI) {
+ int32_t index = i.InputInt32(1);
+ ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
+ scratch0, scratch1, mode);
+ __ str(value, MemOperand(object, index));
+ } else {
+ DCHECK_EQ(kMode_Offset_RR, addressing_mode);
+ Register index(i.InputRegister(1));
+ ool = new (zone()) OutOfLineRecordWrite(this, object, index, value,
+ scratch0, scratch1, mode);
+ __ str(value, MemOperand(object, index));
+ }
__ CheckPageFlag(object, scratch0,
MemoryChunk::kPointersFromHereAreInterestingMask, ne,
ool->entry());
__ bind(ool->exit());
break;
}
+ case kArchStackSlot: {
+ FrameOffset offset =
+ frame_access_state()->GetFrameOffset(i.InputInt32(0));
+ Register base;
+ if (offset.from_stack_pointer()) {
+ base = sp;
+ } else {
+ base = fp;
+ }
+ __ add(i.OutputRegister(0), base, Operand(offset.offset()));
+ break;
+ }
case kArmAdd:
__ add(i.OutputRegister(), i.InputRegister(0), i.InputOperand2(1),
i.OutputSBit());
@@ -622,6 +673,13 @@
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
+ case kArmSbfx: {
+ CpuFeatureScope scope(masm(), ARMv7);
+ __ sbfx(i.OutputRegister(), i.InputRegister(0), i.InputInt8(1),
+ i.InputInt8(2));
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
case kArmSxtb:
__ sxtb(i.OutputRegister(), i.InputRegister(0), i.InputInt32(1));
DCHECK_EQ(LeaveCC, i.OutputSBit());
@@ -658,6 +716,12 @@
i.InputInt32(2));
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
+ case kArmRbit: {
+ CpuFeatureScope scope(masm(), ARMv7);
+ __ rbit(i.OutputRegister(), i.InputRegister(0));
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
case kArmClz:
__ clz(i.OutputRegister(), i.InputRegister(0));
DCHECK_EQ(LeaveCC, i.OutputSBit());
@@ -831,6 +895,20 @@
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
+ case kArmVcvtF32S32: {
+ SwVfpRegister scratch = kScratchDoubleReg.low();
+ __ vmov(scratch, i.InputRegister(0));
+ __ vcvt_f32_s32(i.OutputFloat32Register(), scratch);
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
+ case kArmVcvtF32U32: {
+ SwVfpRegister scratch = kScratchDoubleReg.low();
+ __ vmov(scratch, i.InputRegister(0));
+ __ vcvt_f32_u32(i.OutputFloat32Register(), scratch);
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
case kArmVcvtF64S32: {
SwVfpRegister scratch = kScratchDoubleReg.low();
__ vmov(scratch, i.InputRegister(0));
@@ -845,6 +923,20 @@
DCHECK_EQ(LeaveCC, i.OutputSBit());
break;
}
+ case kArmVcvtS32F32: {
+ SwVfpRegister scratch = kScratchDoubleReg.low();
+ __ vcvt_s32_f32(scratch, i.InputFloat32Register(0));
+ __ vmov(i.OutputRegister(), scratch);
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
+ case kArmVcvtU32F32: {
+ SwVfpRegister scratch = kScratchDoubleReg.low();
+ __ vcvt_u32_f32(scratch, i.InputFloat32Register(0));
+ __ vmov(i.OutputRegister(), scratch);
+ DCHECK_EQ(LeaveCC, i.OutputSBit());
+ break;
+ }
case kArmVcvtS32F64: {
SwVfpRegister scratch = kScratchDoubleReg.low();
__ vcvt_s32_f64(scratch, i.InputFloat64Register(0));
@@ -1098,8 +1190,6 @@
// remaining stack slots.
if (FLAG_code_comments) __ RecordComment("-- OSR entrypoint --");
osr_pc_offset_ = __ pc_offset();
- // TODO(titzer): cannot address target function == local #-1
- __ ldr(r1, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
stack_shrink_slots -= OsrHelper(info()).UnoptimizedFrameSlots();
}
diff --git a/src/compiler/arm/instruction-codes-arm.h b/src/compiler/arm/instruction-codes-arm.h
index 401100b..50fa555 100644
--- a/src/compiler/arm/instruction-codes-arm.h
+++ b/src/compiler/arm/instruction-codes-arm.h
@@ -36,6 +36,7 @@
V(ArmMvn) \
V(ArmBfc) \
V(ArmUbfx) \
+ V(ArmSbfx) \
V(ArmSxtb) \
V(ArmSxth) \
V(ArmSxtab) \
@@ -43,6 +44,7 @@
V(ArmUxtb) \
V(ArmUxth) \
V(ArmUxtab) \
+ V(ArmRbit) \
V(ArmUxtah) \
V(ArmVcmpF32) \
V(ArmVaddF32) \
@@ -76,8 +78,12 @@
V(ArmVrintnF64) \
V(ArmVcvtF32F64) \
V(ArmVcvtF64F32) \
+ V(ArmVcvtF32S32) \
+ V(ArmVcvtF32U32) \
V(ArmVcvtF64S32) \
V(ArmVcvtF64U32) \
+ V(ArmVcvtS32F32) \
+ V(ArmVcvtU32F32) \
V(ArmVcvtS32F64) \
V(ArmVcvtU32F64) \
V(ArmVmovLowU32F64) \
@@ -100,7 +106,6 @@
V(ArmPush) \
V(ArmPoke)
-
// Addressing modes represent the "shape" of inputs to an instruction.
// Many instructions support multiple addressing modes. Addressing modes
// are encoded into the InstructionCode of the instruction and tell the
diff --git a/src/compiler/arm/instruction-scheduler-arm.cc b/src/compiler/arm/instruction-scheduler-arm.cc
index f36802c..d950e8c 100644
--- a/src/compiler/arm/instruction-scheduler-arm.cc
+++ b/src/compiler/arm/instruction-scheduler-arm.cc
@@ -38,6 +38,7 @@
case kArmMvn:
case kArmBfc:
case kArmUbfx:
+ case kArmSbfx:
case kArmSxtb:
case kArmSxth:
case kArmSxtab:
@@ -46,6 +47,7 @@
case kArmUxth:
case kArmUxtab:
case kArmUxtah:
+ case kArmRbit:
case kArmVcmpF32:
case kArmVaddF32:
case kArmVsubF32:
@@ -78,8 +80,12 @@
case kArmVrintnF64:
case kArmVcvtF32F64:
case kArmVcvtF64F32:
+ case kArmVcvtF32S32:
+ case kArmVcvtF32U32:
case kArmVcvtF64S32:
case kArmVcvtF64U32:
+ case kArmVcvtS32F32:
+ case kArmVcvtU32F32:
case kArmVcvtS32F64:
case kArmVcvtU32F64:
case kArmVmovLowU32F64:
diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc
index f3deae7..14b30b1 100644
--- a/src/compiler/arm/instruction-selector-arm.cc
+++ b/src/compiler/arm/instruction-selector-arm.cc
@@ -327,8 +327,9 @@
case MachineRepresentation::kWord32:
opcode = kArmLdr;
break;
- case MachineRepresentation::kNone: // Fall through.
- case MachineRepresentation::kWord64:
+ case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kSimd128: // Fall through.
+ case MachineRepresentation::kNone:
UNREACHABLE();
return;
}
@@ -355,10 +356,19 @@
if (write_barrier_kind != kNoWriteBarrier) {
DCHECK_EQ(MachineRepresentation::kTagged, rep);
+ AddressingMode addressing_mode;
InstructionOperand inputs[3];
size_t input_count = 0;
inputs[input_count++] = g.UseUniqueRegister(base);
- inputs[input_count++] = g.UseUniqueRegister(index);
+ // OutOfLineRecordWrite uses the index in an 'add' instruction as well as
+ // for the store itself, so we must check compatibility with both.
+ if (g.CanBeImmediate(index, kArmAdd) && g.CanBeImmediate(index, kArmStr)) {
+ inputs[input_count++] = g.UseImmediate(index);
+ addressing_mode = kMode_Offset_RI;
+ } else {
+ inputs[input_count++] = g.UseUniqueRegister(index);
+ addressing_mode = kMode_Offset_RR;
+ }
inputs[input_count++] = (write_barrier_kind == kMapWriteBarrier)
? g.UseRegister(value)
: g.UseUniqueRegister(value);
@@ -380,6 +390,7 @@
InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()};
size_t const temp_count = arraysize(temps);
InstructionCode code = kArchStoreWithWriteBarrier;
+ code |= AddressingModeField::encode(addressing_mode);
code |= MiscField::encode(static_cast<int>(record_write_mode));
Emit(code, 0, nullptr, input_count, inputs, temp_count, temps);
} else {
@@ -402,8 +413,9 @@
case MachineRepresentation::kWord32:
opcode = kArmStr;
break;
- case MachineRepresentation::kNone: // Fall through.
- case MachineRepresentation::kWord64:
+ case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kSimd128: // Fall through.
+ case MachineRepresentation::kNone:
UNREACHABLE();
return;
}
@@ -442,9 +454,10 @@
case MachineRepresentation::kFloat64:
opcode = kCheckedLoadFloat64;
break;
- case MachineRepresentation::kBit: // Fall through.
- case MachineRepresentation::kTagged: // Fall through.
- case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kBit: // Fall through.
+ case MachineRepresentation::kTagged: // Fall through.
+ case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kSimd128: // Fall through.
case MachineRepresentation::kNone:
UNREACHABLE();
return;
@@ -483,9 +496,10 @@
case MachineRepresentation::kFloat64:
opcode = kCheckedStoreFloat64;
break;
- case MachineRepresentation::kBit: // Fall through.
- case MachineRepresentation::kTagged: // Fall through.
- case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kBit: // Fall through.
+ case MachineRepresentation::kTagged: // Fall through.
+ case MachineRepresentation::kWord64: // Fall through.
+ case MachineRepresentation::kSimd128: // Fall through.
case MachineRepresentation::kNone:
UNREACHABLE();
return;
@@ -551,43 +565,67 @@
if (m.right().HasValue()) {
uint32_t const value = m.right().Value();
uint32_t width = base::bits::CountPopulation32(value);
- uint32_t msb = base::bits::CountLeadingZeros32(value);
- // Try to interpret this AND as UBFX.
- if (IsSupported(ARMv7) && width != 0 && msb + width == 32) {
- DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
- if (m.left().IsWord32Shr()) {
- Int32BinopMatcher mleft(m.left().node());
- if (mleft.right().IsInRange(0, 31)) {
- // UBFX cannot extract bits past the register size, however since
- // shifting the original value would have introduced some zeros we can
- // still use UBFX with a smaller mask and the remaining bits will be
- // zeros.
- uint32_t const lsb = mleft.right().Value();
- return EmitUbfx(this, node, mleft.left().node(), lsb,
- std::min(width, 32 - lsb));
+ uint32_t leading_zeros = base::bits::CountLeadingZeros32(value);
+
+ // Try to merge SHR operations on the left hand input into this AND.
+ if (m.left().IsWord32Shr()) {
+ Int32BinopMatcher mshr(m.left().node());
+ if (mshr.right().HasValue()) {
+ uint32_t const shift = mshr.right().Value();
+
+ if (((shift == 8) || (shift == 16) || (shift == 24)) &&
+ ((value == 0xff) || (value == 0xffff))) {
+ // Merge SHR into AND by emitting a UXTB or UXTH instruction with a
+ // bytewise rotation.
+ Emit((value == 0xff) ? kArmUxtb : kArmUxth,
+ g.DefineAsRegister(m.node()), g.UseRegister(mshr.left().node()),
+ g.TempImmediate(mshr.right().Value()));
+ return;
+ } else if (IsSupported(ARMv7) && (width != 0) &&
+ ((leading_zeros + width) == 32)) {
+ // Merge Shr into And by emitting a UBFX instruction.
+ DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
+ if ((1 <= shift) && (shift <= 31)) {
+ // UBFX cannot extract bits past the register size, however since
+ // shifting the original value would have introduced some zeros we
+ // can still use UBFX with a smaller mask and the remaining bits
+ // will be zeros.
+ EmitUbfx(this, node, mshr.left().node(), shift,
+ std::min(width, 32 - shift));
+ return;
+ }
}
}
- return EmitUbfx(this, node, m.left().node(), 0, width);
+ } else if (value == 0xffff) {
+ // Emit UXTH for this AND. We don't bother testing for UXTB, as it's no
+ // better than AND 0xff for this operation.
+ Emit(kArmUxth, g.DefineAsRegister(m.node()),
+ g.UseRegister(m.left().node()), g.TempImmediate(0));
+ return;
}
- // Try to interpret this AND as BIC.
if (g.CanBeImmediate(~value)) {
+ // Emit BIC for this AND by inverting the immediate value first.
Emit(kArmBic | AddressingModeField::encode(kMode_Operand2_I),
g.DefineAsRegister(node), g.UseRegister(m.left().node()),
g.TempImmediate(~value));
return;
}
- // Try to interpret this AND as UXTH.
- if (value == 0xffff) {
- Emit(kArmUxth, g.DefineAsRegister(m.node()),
- g.UseRegister(m.left().node()), g.TempImmediate(0));
- return;
- }
- // Try to interpret this AND as BFC.
- if (IsSupported(ARMv7)) {
+ if (!g.CanBeImmediate(value) && IsSupported(ARMv7)) {
+ // If value has 9 to 23 contiguous set bits, and has the lsb set, we can
+ // replace this AND with UBFX. Other contiguous bit patterns have already
+ // been handled by BIC or will be handled by AND.
+ if ((width != 0) && ((leading_zeros + width) == 32) &&
+ (9 <= leading_zeros) && (leading_zeros <= 23)) {
+ DCHECK_EQ(0u, base::bits::CountTrailingZeros32(value));
+ EmitUbfx(this, node, m.left().node(), 0, width);
+ return;
+ }
+
width = 32 - width;
- msb = base::bits::CountLeadingZeros32(~value);
+ leading_zeros = base::bits::CountLeadingZeros32(~value);
uint32_t lsb = base::bits::CountTrailingZeros32(~value);
- if (msb + width + lsb == 32) {
+ if ((leading_zeros + width + lsb) == 32) {
+ // This AND can be replaced with BFC.
Emit(kArmBfc, g.DefineSameAsFirst(node), g.UseRegister(m.left().node()),
g.TempImmediate(lsb), g.TempImmediate(width));
return;
@@ -699,14 +737,23 @@
Int32BinopMatcher m(node);
if (CanCover(m.node(), m.left().node()) && m.left().IsWord32Shl()) {
Int32BinopMatcher mleft(m.left().node());
- if (mleft.right().Is(16) && m.right().Is(16)) {
- Emit(kArmSxth, g.DefineAsRegister(node),
- g.UseRegister(mleft.left().node()), g.TempImmediate(0));
- return;
- } else if (mleft.right().Is(24) && m.right().Is(24)) {
- Emit(kArmSxtb, g.DefineAsRegister(node),
- g.UseRegister(mleft.left().node()), g.TempImmediate(0));
- return;
+ if (m.right().HasValue() && mleft.right().HasValue()) {
+ uint32_t sar = m.right().Value();
+ uint32_t shl = mleft.right().Value();
+ if ((sar == shl) && (sar == 16)) {
+ Emit(kArmSxth, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()), g.TempImmediate(0));
+ return;
+ } else if ((sar == shl) && (sar == 24)) {
+ Emit(kArmSxtb, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()), g.TempImmediate(0));
+ return;
+ } else if (IsSupported(ARMv7) && (sar >= shl)) {
+ Emit(kArmSbfx, g.DefineAsRegister(node),
+ g.UseRegister(mleft.left().node()), g.TempImmediate(sar - shl),
+ g.TempImmediate(32 - sar));
+ return;
+ }
}
}
VisitShift(this, node, TryMatchASR);
@@ -726,6 +773,12 @@
void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
+void InstructionSelector::VisitWord32ReverseBits(Node* node) {
+ DCHECK(IsSupported(ARMv7));
+ VisitRR(this, kArmRbit, node);
+}
+
+
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
@@ -921,6 +974,16 @@
}
+void InstructionSelector::VisitRoundInt32ToFloat32(Node* node) {
+ VisitRR(this, kArmVcvtF32S32, node);
+}
+
+
+void InstructionSelector::VisitRoundUint32ToFloat32(Node* node) {
+ VisitRR(this, kArmVcvtF32U32, node);
+}
+
+
void InstructionSelector::VisitChangeInt32ToFloat64(Node* node) {
VisitRR(this, kArmVcvtF64S32, node);
}
@@ -931,6 +994,16 @@
}
+void InstructionSelector::VisitTruncateFloat32ToInt32(Node* node) {
+ VisitRR(this, kArmVcvtS32F32, node);
+}
+
+
+void InstructionSelector::VisitTruncateFloat32ToUint32(Node* node) {
+ VisitRR(this, kArmVcvtU32F32, node);
+}
+
+
void InstructionSelector::VisitChangeFloat64ToInt32(Node* node) {
VisitRR(this, kArmVcvtS32F64, node);
}
@@ -1591,6 +1664,9 @@
MachineOperatorBuilder::Flags flags =
MachineOperatorBuilder::kInt32DivIsSafe |
MachineOperatorBuilder::kUint32DivIsSafe;
+ if (CpuFeatures::IsSupported(ARMv7)) {
+ flags |= MachineOperatorBuilder::kWord32ReverseBits;
+ }
if (CpuFeatures::IsSupported(ARMv8)) {
flags |= MachineOperatorBuilder::kFloat32RoundDown |
MachineOperatorBuilder::kFloat64RoundDown |