Revert "[turbofan] Further optimize DataView accesses."
This reverts commit c46915b931
.
Reason for revert: Disasm failures https://ci.chromium.org/p/v8/builders/luci.v8.ci/V8%20Linux%20-%20debug/21727
Original change's description:
> [turbofan] Further optimize DataView accesses.
>
> This adds support for unaligned load/store access to the DataView
> backing store and uses byteswap operations to fix up the endianess
> when necessary. This changes the Word32ReverseBytes operator to be
> a required operator and adds the missing support on the Intel and
> ARM platforms (on 64-bit platforms the Word64ReverseBytes operator
> is also mandatory now).
>
> This further improves the performance on the dataviewperf.js test
> mentioned in the tracking bug by up to 40%, and at the same time
> reduces the code complexity in the EffectControlLinearizer.
>
> Bug: chromium:225811
> Change-Id: I296170b828c2ccc1c317ed37840b564aa14cdec2
> Reviewed-on: https://chromium-review.googlesource.com/1172777
> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
> Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#55099}
TBR=sigurds@chromium.org,bmeurer@chromium.org
Change-Id: If7a62e3a1a4ad26823fcbd2ab6eb4c053ad11c49
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:225811
Reviewed-on: https://chromium-review.googlesource.com/1174171
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55107}
This commit is contained in:
parent
3e545e4045
commit
6a62d88e9b
@ -2061,13 +2061,6 @@ void Assembler::rbit(Register dst, Register src, Condition cond) {
|
||||
emit(cond | 0x6FF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
|
||||
}
|
||||
|
||||
void Assembler::rev(Register dst, Register src, Condition cond) {
|
||||
// Instruction details available in ARM DDI 0406C.b, A8.8.144.
|
||||
// cond(31-28) | 011010111111(27-16) | Rd(15-12) | 11110011(11-4) | Rm(3-0)
|
||||
DCHECK(dst != pc);
|
||||
DCHECK(src != pc);
|
||||
emit(cond | 0x6BF * B16 | dst.code() * B12 | 0xF3 * B4 | src.code());
|
||||
}
|
||||
|
||||
// Status register access instructions.
|
||||
void Assembler::mrs(Register dst, SRegister s, Condition cond) {
|
||||
|
@ -899,7 +899,6 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
|
||||
// Reverse the bits in a register.
|
||||
void rbit(Register dst, Register src, Condition cond = al);
|
||||
void rev(Register dst, Register src, Condition cond = al);
|
||||
|
||||
// Status register access instructions
|
||||
|
||||
|
@ -1194,9 +1194,6 @@ void Decoder::DecodeType3(Instruction* instr) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (instr->Bits(27, 16) == 0x6BF &&
|
||||
instr->Bits(11, 4) == 0xF3) {
|
||||
Format(instr, "rev'cond 'rd, 'rm");
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -2771,11 +2771,6 @@ void Simulator::DecodeType3(Instruction* instr) {
|
||||
set_register(rd, rn_val + static_cast<int16_t>(rm_val));
|
||||
}
|
||||
}
|
||||
} else if (instr->Bits(27, 16) == 0x6BF &&
|
||||
instr->Bits(11, 4) == 0xF3) {
|
||||
// Rev.
|
||||
uint32_t rm_val = get_register(instr->RmValue());
|
||||
set_register(rd, ByteReverse(rm_val));
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
@ -830,12 +830,6 @@ void TurboAssembler::Rbit(const Register& rd, const Register& rn) {
|
||||
rbit(rd, rn);
|
||||
}
|
||||
|
||||
void TurboAssembler::Rev(const Register& rd, const Register& rn) {
|
||||
DCHECK(allow_macro_instructions());
|
||||
DCHECK(!rd.IsZero());
|
||||
rev(rd, rn);
|
||||
}
|
||||
|
||||
void TurboAssembler::Ret(const Register& xn) {
|
||||
DCHECK(allow_macro_instructions());
|
||||
DCHECK(!xn.IsZero());
|
||||
|
@ -942,7 +942,6 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
|
||||
inline void Fmin(const VRegister& fd, const VRegister& fn,
|
||||
const VRegister& fm);
|
||||
inline void Rbit(const Register& rd, const Register& rn);
|
||||
inline void Rev(const Register& rd, const Register& rn);
|
||||
|
||||
enum AdrHint {
|
||||
// The target must be within the immediate range of adr.
|
||||
|
@ -1149,10 +1149,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
}
|
||||
case kArmRev:
|
||||
__ rev(i.OutputRegister(), i.InputRegister(0));
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
break;
|
||||
case kArmClz:
|
||||
__ clz(i.OutputRegister(), i.InputRegister(0));
|
||||
DCHECK_EQ(LeaveCC, i.OutputSBit());
|
||||
|
@ -46,7 +46,6 @@ namespace compiler {
|
||||
V(ArmUxth) \
|
||||
V(ArmUxtab) \
|
||||
V(ArmRbit) \
|
||||
V(ArmRev) \
|
||||
V(ArmUxtah) \
|
||||
V(ArmAddPair) \
|
||||
V(ArmSubPair) \
|
||||
|
@ -49,7 +49,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArmUxtab:
|
||||
case kArmUxtah:
|
||||
case kArmRbit:
|
||||
case kArmRev:
|
||||
case kArmAddPair:
|
||||
case kArmSubPair:
|
||||
case kArmMulPair:
|
||||
|
@ -1100,9 +1100,7 @@ void InstructionSelector::VisitWord32ReverseBits(Node* node) {
|
||||
|
||||
void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) {
|
||||
VisitRR(this, kArmRev, node);
|
||||
}
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
|
||||
|
||||
|
@ -1267,12 +1267,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kArm64Rbit32:
|
||||
__ Rbit(i.OutputRegister32(), i.InputRegister32(0));
|
||||
break;
|
||||
case kArm64Rev:
|
||||
__ Rev(i.OutputRegister64(), i.InputRegister64(0));
|
||||
break;
|
||||
case kArm64Rev32:
|
||||
__ Rev(i.OutputRegister32(), i.InputRegister32(0));
|
||||
break;
|
||||
case kArm64Cmp:
|
||||
__ Cmp(i.InputOrZeroRegister64(0), i.InputOperand2_64(1));
|
||||
break;
|
||||
|
@ -77,8 +77,6 @@ namespace compiler {
|
||||
V(Arm64Bfi) \
|
||||
V(Arm64Rbit) \
|
||||
V(Arm64Rbit32) \
|
||||
V(Arm64Rev) \
|
||||
V(Arm64Rev32) \
|
||||
V(Arm64TestAndBranch32) \
|
||||
V(Arm64TestAndBranch) \
|
||||
V(Arm64CompareAndBranch32) \
|
||||
|
@ -79,8 +79,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kArm64Bfi:
|
||||
case kArm64Rbit:
|
||||
case kArm64Rbit32:
|
||||
case kArm64Rev:
|
||||
case kArm64Rev32:
|
||||
case kArm64Float32Cmp:
|
||||
case kArm64Float32Add:
|
||||
case kArm64Float32Sub:
|
||||
|
@ -1189,8 +1189,6 @@ void InstructionSelector::VisitWord64Ror(Node* node) {
|
||||
V(Word32Clz, kArm64Clz32) \
|
||||
V(Word32ReverseBits, kArm64Rbit32) \
|
||||
V(Word64ReverseBits, kArm64Rbit) \
|
||||
V(Word32ReverseBytes, kArm64Rev32) \
|
||||
V(Word64ReverseBytes, kArm64Rev) \
|
||||
V(ChangeFloat32ToFloat64, kArm64Float32ToFloat64) \
|
||||
V(RoundInt32ToFloat32, kArm64Int32ToFloat32) \
|
||||
V(RoundUint32ToFloat32, kArm64Uint32ToFloat32) \
|
||||
@ -1274,6 +1272,10 @@ void InstructionSelector::VisitWord32Ctz(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64Ctz(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32Popcnt(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64Popcnt(Node* node) { UNREACHABLE(); }
|
||||
|
@ -3752,59 +3752,6 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::BuildReverseBytes(ExternalArrayType type,
|
||||
Node* value) {
|
||||
switch (type) {
|
||||
case kExternalInt8Array:
|
||||
case kExternalUint8Array:
|
||||
case kExternalUint8ClampedArray:
|
||||
return value;
|
||||
|
||||
case kExternalInt16Array: {
|
||||
Node* result = __ Word32ReverseBytes(value);
|
||||
result = __ Word32Sar(result, __ Int32Constant(16));
|
||||
return result;
|
||||
}
|
||||
|
||||
case kExternalUint16Array: {
|
||||
Node* result = __ Word32ReverseBytes(value);
|
||||
result = __ Word32Shr(result, __ Int32Constant(16));
|
||||
return result;
|
||||
}
|
||||
|
||||
case kExternalInt32Array: // Fall through.
|
||||
case kExternalUint32Array:
|
||||
return __ Word32ReverseBytes(value);
|
||||
|
||||
case kExternalFloat32Array: {
|
||||
Node* result = __ BitcastFloat32ToInt32(value);
|
||||
result = __ Word32ReverseBytes(result);
|
||||
result = __ BitcastInt32ToFloat32(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
case kExternalFloat64Array: {
|
||||
if (machine()->Is64()) {
|
||||
Node* result = __ BitcastFloat64ToInt64(value);
|
||||
result = __ Word64ReverseBytes(result);
|
||||
result = __ BitcastInt64ToFloat64(result);
|
||||
return result;
|
||||
} else {
|
||||
Node* lo = __ Word32ReverseBytes(__ Float64ExtractLowWord32(value));
|
||||
Node* hi = __ Word32ReverseBytes(__ Float64ExtractHighWord32(value));
|
||||
Node* result = __ Float64Constant(0.0);
|
||||
result = __ Float64InsertLowWord32(result, hi);
|
||||
result = __ Float64InsertHighWord32(result, lo);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
case kExternalBigInt64Array:
|
||||
case kExternalBigUint64Array:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) {
|
||||
ExternalArrayType element_type = ExternalArrayTypeOf(node->op());
|
||||
Node* buffer = node->InputAt(0);
|
||||
@ -3822,34 +3769,166 @@ Node* EffectControlLinearizer::LowerLoadDataViewElement(Node* node) {
|
||||
// ArrayBuffer (if there's any) as long as we are still operating on it.
|
||||
__ Retain(buffer);
|
||||
|
||||
MachineType const machine_type =
|
||||
AccessBuilder::ForTypedArrayElement(element_type, true).machine_type;
|
||||
ElementAccess access_int8 = AccessBuilder::ForTypedArrayElement(
|
||||
kExternalInt8Array, true, LoadSensitivity::kCritical);
|
||||
ElementAccess access_uint8 = AccessBuilder::ForTypedArrayElement(
|
||||
kExternalUint8Array, true, LoadSensitivity::kCritical);
|
||||
|
||||
Node* value = __ LoadUnaligned(machine_type, storage, index);
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel(machine_type.representation());
|
||||
switch (element_type) {
|
||||
case kExternalUint8Array:
|
||||
return __ LoadElement(access_uint8, storage, index);
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{ // Little-endian load.
|
||||
#if V8_TARGET_LITTLE_ENDIAN
|
||||
__ Goto(&done, value);
|
||||
#else
|
||||
__ Goto(&done, BuildReverseBytes(element_type, value));
|
||||
#endif // V8_TARGET_LITTLE_ENDIAN
|
||||
case kExternalInt8Array:
|
||||
return __ LoadElement(access_int8, storage, index);
|
||||
|
||||
case kExternalUint16Array: // Fall through.
|
||||
case kExternalInt16Array: {
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel(MachineRepresentation::kWord32);
|
||||
|
||||
// If we're doing an Int16 load, sign-extend the most significant byte
|
||||
// by loading it as an Int8 instead of Uint8.
|
||||
ElementAccess access_msb =
|
||||
element_type == kExternalInt16Array ? access_int8 : access_uint8;
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian load.
|
||||
Node* b0 = __ LoadElement(access_uint8, storage, index);
|
||||
Node* b1 = __ LoadElement(access_msb, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)));
|
||||
|
||||
// result = (b1 << 8) + b0
|
||||
Node* result = __ Int32Add(__ Word32Shl(b1, __ Int32Constant(8)), b0);
|
||||
__ Goto(&done, result);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian load.
|
||||
Node* b0 = __ LoadElement(access_msb, storage, index);
|
||||
Node* b1 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)));
|
||||
|
||||
// result = (b0 << 8) + b1;
|
||||
Node* result = __ Int32Add(__ Word32Shl(b0, __ Int32Constant(8)), b1);
|
||||
__ Goto(&done, result);
|
||||
}
|
||||
|
||||
// We're done, return {result}.
|
||||
__ Bind(&done);
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
case kExternalUint32Array: // Fall through.
|
||||
case kExternalInt32Array: // Fall through.
|
||||
case kExternalFloat32Array: {
|
||||
Node* b0 = __ LoadElement(access_uint8, storage, index);
|
||||
Node* b1 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)));
|
||||
Node* b2 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)));
|
||||
Node* b3 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)));
|
||||
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel(MachineRepresentation::kWord32);
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian load.
|
||||
// result = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
Node* result =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b3, __ Int32Constant(24)),
|
||||
__ Word32Shl(b2, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b1, __ Int32Constant(8)), b0));
|
||||
__ Goto(&done, result);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian load.
|
||||
// result = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
||||
Node* result =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b0, __ Int32Constant(24)),
|
||||
__ Word32Shl(b1, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b2, __ Int32Constant(8)), b3));
|
||||
__ Goto(&done, result);
|
||||
}
|
||||
|
||||
// We're done, return {result}.
|
||||
__ Bind(&done);
|
||||
if (element_type == kExternalFloat32Array) {
|
||||
return __ BitcastInt32ToFloat32(done.PhiAt(0));
|
||||
} else {
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
case kExternalFloat64Array: {
|
||||
Node* b0 = __ LoadElement(access_uint8, storage, index);
|
||||
Node* b1 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)));
|
||||
Node* b2 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)));
|
||||
Node* b3 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)));
|
||||
Node* b4 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(4)));
|
||||
Node* b5 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(5)));
|
||||
Node* b6 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(6)));
|
||||
Node* b7 = __ LoadElement(access_uint8, storage,
|
||||
__ Int32Add(index, __ Int32Constant(7)));
|
||||
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel(MachineRepresentation::kWord32,
|
||||
MachineRepresentation::kWord32);
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian load.
|
||||
// low_word = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
|
||||
// high_word = (b7 << 24) | (b6 << 16) | (b5 << 8) | b4;
|
||||
Node* low_word =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b3, __ Int32Constant(24)),
|
||||
__ Word32Shl(b2, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b1, __ Int32Constant(8)), b0));
|
||||
Node* high_word =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b7, __ Int32Constant(24)),
|
||||
__ Word32Shl(b6, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b5, __ Int32Constant(8)), b4));
|
||||
__ Goto(&done, low_word, high_word);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian load.
|
||||
// high_word = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
|
||||
// low_word = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
|
||||
Node* high_word =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b0, __ Int32Constant(24)),
|
||||
__ Word32Shl(b1, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b2, __ Int32Constant(8)), b3));
|
||||
Node* low_word =
|
||||
__ Word32Or(__ Word32Or(__ Word32Shl(b4, __ Int32Constant(24)),
|
||||
__ Word32Shl(b5, __ Int32Constant(16))),
|
||||
__ Word32Or(__ Word32Shl(b6, __ Int32Constant(8)), b7));
|
||||
__ Goto(&done, low_word, high_word);
|
||||
}
|
||||
|
||||
// We're done, store the low and high words into a float64.
|
||||
__ Bind(&done);
|
||||
Node* result = __ Float64Constant(0.0);
|
||||
result = __ Float64InsertLowWord32(result, done.PhiAt(0));
|
||||
result = __ Float64InsertHighWord32(result, done.PhiAt(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{ // Big-endian load.
|
||||
#if V8_TARGET_LITTLE_ENDIAN
|
||||
__ Goto(&done, BuildReverseBytes(element_type, value));
|
||||
#else
|
||||
__ Goto(&done, value);
|
||||
#endif // V8_TARGET_LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
// We're done, return {result}.
|
||||
__ Bind(&done);
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
void EffectControlLinearizer::LowerStoreDataViewElement(Node* node) {
|
||||
@ -3870,35 +3949,165 @@ void EffectControlLinearizer::LowerStoreDataViewElement(Node* node) {
|
||||
// ArrayBuffer (if there's any) as long as we are still operating on it.
|
||||
__ Retain(buffer);
|
||||
|
||||
MachineType const machine_type =
|
||||
AccessBuilder::ForTypedArrayElement(element_type, true).machine_type;
|
||||
ElementAccess access =
|
||||
AccessBuilder::ForTypedArrayElement(kExternalUint8Array, true);
|
||||
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel(machine_type.representation());
|
||||
switch (element_type) {
|
||||
case kExternalUint8Array: // Fall through.
|
||||
case kExternalInt8Array: {
|
||||
Node* b0 = __ Word32And(value, __ Int32Constant(0xFF));
|
||||
__ StoreElement(access, storage, index, b0);
|
||||
break;
|
||||
}
|
||||
case kExternalUint16Array: // Fall through.
|
||||
case kExternalInt16Array: {
|
||||
Node* b0 = __ Word32And(value, __ Int32Constant(0xFF));
|
||||
Node* b1 = __ Word32And(__ Word32Shr(value, __ Int32Constant(8)),
|
||||
__ Int32Constant(0xFF));
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{ // Little-endian store.
|
||||
#if V8_TARGET_LITTLE_ENDIAN
|
||||
__ Goto(&done, value);
|
||||
#else
|
||||
__ Goto(&done, BuildReverseBytes(element_type, value));
|
||||
#endif // V8_TARGET_LITTLE_ENDIAN
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel();
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian store.
|
||||
__ StoreElement(access, storage, index, b0);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b1);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian store.
|
||||
__ StoreElement(access, storage, index, b1);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b0);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
break;
|
||||
}
|
||||
|
||||
case kExternalUint32Array: // Fall through.
|
||||
case kExternalInt32Array: // Fall through.
|
||||
case kExternalFloat32Array: {
|
||||
if (element_type == kExternalFloat32Array) {
|
||||
value = __ BitcastFloat32ToInt32(value);
|
||||
}
|
||||
|
||||
Node* b0 = __ Word32And(value, __ Int32Constant(0xFF));
|
||||
Node* b1 = __ Word32And(__ Word32Shr(value, __ Int32Constant(8)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b2 = __ Word32And(__ Word32Shr(value, __ Int32Constant(16)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b3 = __ Word32Shr(value, __ Int32Constant(24));
|
||||
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel();
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian store.
|
||||
__ StoreElement(access, storage, index, b0);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b1);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)), b2);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)), b3);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian store.
|
||||
__ StoreElement(access, storage, index, b3);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b2);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)), b1);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)), b0);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
break;
|
||||
}
|
||||
|
||||
case kExternalFloat64Array: {
|
||||
Node* low_word = __ Float64ExtractLowWord32(value);
|
||||
Node* high_word = __ Float64ExtractHighWord32(value);
|
||||
|
||||
Node* b0 = __ Word32And(low_word, __ Int32Constant(0xFF));
|
||||
Node* b1 = __ Word32And(__ Word32Shr(low_word, __ Int32Constant(8)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b2 = __ Word32And(__ Word32Shr(low_word, __ Int32Constant(16)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b3 = __ Word32Shr(low_word, __ Int32Constant(24));
|
||||
|
||||
Node* b4 = __ Word32And(high_word, __ Int32Constant(0xFF));
|
||||
Node* b5 = __ Word32And(__ Word32Shr(high_word, __ Int32Constant(8)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b6 = __ Word32And(__ Word32Shr(high_word, __ Int32Constant(16)),
|
||||
__ Int32Constant(0xFF));
|
||||
Node* b7 = __ Word32Shr(high_word, __ Int32Constant(24));
|
||||
|
||||
auto big_endian = __ MakeLabel();
|
||||
auto done = __ MakeLabel();
|
||||
|
||||
__ GotoIfNot(is_little_endian, &big_endian);
|
||||
{
|
||||
// Little-endian store.
|
||||
__ StoreElement(access, storage, index, b0);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b1);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)), b2);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)), b3);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(4)), b4);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(5)), b5);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(6)), b6);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(7)), b7);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{
|
||||
// Big-endian store.
|
||||
__ StoreElement(access, storage, index, b7);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(1)), b6);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(2)), b5);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(3)), b4);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(4)), b3);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(5)), b2);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(6)), b1);
|
||||
__ StoreElement(access, storage,
|
||||
__ Int32Add(index, __ Int32Constant(7)), b0);
|
||||
__ Goto(&done);
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
__ Bind(&big_endian);
|
||||
{ // Big-endian store.
|
||||
#if V8_TARGET_LITTLE_ENDIAN
|
||||
__ Goto(&done, BuildReverseBytes(element_type, value));
|
||||
#else
|
||||
__ Goto(&done, value);
|
||||
#endif // V8_TARGET_LITTLE_ENDIAN
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
__ StoreUnaligned(machine_type.representation(), storage, index,
|
||||
done.PhiAt(0));
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerLoadTypedElement(Node* node) {
|
||||
ExternalArrayType array_type = ExternalArrayTypeOf(node->op());
|
||||
Node* buffer = node->InputAt(0);
|
||||
|
@ -178,7 +178,6 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
|
||||
const VectorSlotPair& feedback,
|
||||
Node* value,
|
||||
Node* frame_state);
|
||||
Node* BuildReverseBytes(ExternalArrayType type, Node* value);
|
||||
Node* BuildFloat64RoundDown(Node* value);
|
||||
Node* BuildFloat64RoundTruncate(Node* input);
|
||||
Node* ComputeIntegerHash(Node* value);
|
||||
|
@ -155,28 +155,6 @@ Node* GraphAssembler::Load(MachineType rep, Node* object, Node* offset) {
|
||||
current_effect_, current_control_);
|
||||
}
|
||||
|
||||
Node* GraphAssembler::StoreUnaligned(MachineRepresentation rep, Node* object,
|
||||
Node* offset, Node* value) {
|
||||
Operator const* const op =
|
||||
(rep == MachineRepresentation::kWord8 ||
|
||||
machine()->UnalignedStoreSupported(rep))
|
||||
? machine()->Store(StoreRepresentation(rep, kNoWriteBarrier))
|
||||
: machine()->UnalignedStore(rep);
|
||||
return current_effect_ = graph()->NewNode(op, object, offset, value,
|
||||
current_effect_, current_control_);
|
||||
}
|
||||
|
||||
Node* GraphAssembler::LoadUnaligned(MachineType rep, Node* object,
|
||||
Node* offset) {
|
||||
Operator const* const op =
|
||||
(rep.representation() == MachineRepresentation::kWord8 ||
|
||||
machine()->UnalignedLoadSupported(rep.representation()))
|
||||
? machine()->Load(rep)
|
||||
: machine()->UnalignedLoad(rep);
|
||||
return current_effect_ = graph()->NewNode(op, object, offset, current_effect_,
|
||||
current_control_);
|
||||
}
|
||||
|
||||
Node* GraphAssembler::Retain(Node* buffer) {
|
||||
return current_effect_ =
|
||||
graph()->NewNode(common()->Retain(), buffer, current_effect_);
|
||||
|
@ -31,12 +31,8 @@ namespace compiler {
|
||||
V(Float64ExtractLowWord32) \
|
||||
V(Float64ExtractHighWord32) \
|
||||
V(BitcastInt32ToFloat32) \
|
||||
V(BitcastInt64ToFloat64) \
|
||||
V(BitcastFloat32ToInt32) \
|
||||
V(BitcastFloat64ToInt64) \
|
||||
V(Float64Abs) \
|
||||
V(Word32ReverseBytes) \
|
||||
V(Word64ReverseBytes)
|
||||
V(Float64Abs)
|
||||
|
||||
#define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
|
||||
V(WordShl) \
|
||||
@ -219,10 +215,6 @@ class GraphAssembler {
|
||||
Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
|
||||
Node* Load(MachineType rep, Node* object, Node* offset);
|
||||
|
||||
Node* StoreUnaligned(MachineRepresentation rep, Node* object, Node* offset,
|
||||
Node* value);
|
||||
Node* LoadUnaligned(MachineType rep, Node* object, Node* offset);
|
||||
|
||||
Node* Retain(Node* buffer);
|
||||
Node* UnsafePointerAdd(Node* base, Node* external);
|
||||
|
||||
|
@ -1187,9 +1187,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
case kIA32Popcnt:
|
||||
__ Popcnt(i.OutputRegister(), i.InputOperand(0));
|
||||
break;
|
||||
case kIA32Bswap:
|
||||
__ bswap(i.OutputRegister());
|
||||
break;
|
||||
case kArchWordPoisonOnSpeculation:
|
||||
DCHECK_EQ(i.OutputRegister(), i.InputRegister(0));
|
||||
__ and_(i.InputRegister(0), kSpeculationPoisonRegister);
|
||||
|
@ -43,7 +43,6 @@ namespace compiler {
|
||||
V(IA32Lzcnt) \
|
||||
V(IA32Tzcnt) \
|
||||
V(IA32Popcnt) \
|
||||
V(IA32Bswap) \
|
||||
V(LFence) \
|
||||
V(SSEFloat32Cmp) \
|
||||
V(SSEFloat32Add) \
|
||||
|
@ -43,7 +43,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kIA32Lzcnt:
|
||||
case kIA32Tzcnt:
|
||||
case kIA32Popcnt:
|
||||
case kIA32Bswap:
|
||||
case kIA32Lea:
|
||||
case kSSEFloat32Cmp:
|
||||
case kSSEFloat32Add:
|
||||
|
@ -827,10 +827,7 @@ void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) {
|
||||
IA32OperandGenerator g(this);
|
||||
Emit(kIA32Bswap, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)));
|
||||
}
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitInt32Add(Node* node) {
|
||||
IA32OperandGenerator g(this);
|
||||
|
@ -842,10 +842,9 @@ void Int64Lowering::LowerNode(Node* node) {
|
||||
}
|
||||
case IrOpcode::kWord64ReverseBytes: {
|
||||
Node* input = node->InputAt(0);
|
||||
ReplaceNode(node,
|
||||
graph()->NewNode(machine()->Word32ReverseBytes(),
|
||||
GetReplacementHigh(input)),
|
||||
graph()->NewNode(machine()->Word32ReverseBytes(),
|
||||
ReplaceNode(node, graph()->NewNode(machine()->Word32ReverseBytes().op(),
|
||||
GetReplacementHigh(input)),
|
||||
graph()->NewNode(machine()->Word32ReverseBytes().op(),
|
||||
GetReplacementLow(input)));
|
||||
break;
|
||||
}
|
||||
|
@ -139,8 +139,6 @@ MachineType AtomicOpType(Operator const* op) {
|
||||
PURE_BINARY_OP_LIST_64(V) \
|
||||
V(Word32Clz, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word64Clz, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word32ReverseBytes, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word64ReverseBytes, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(BitcastWordToTaggedSigned, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(TruncateFloat64ToWord32, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
|
||||
@ -342,6 +340,8 @@ MachineType AtomicOpType(Operator const* op) {
|
||||
V(Word64Ctz, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word32ReverseBits, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word64ReverseBits, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word32ReverseBytes, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word64ReverseBytes, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Int32AbsWithOverflow, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Int64AbsWithOverflow, Operator::kNoProperties, 1, 0, 1) \
|
||||
V(Word32Popcnt, Operator::kNoProperties, 1, 0, 1) \
|
||||
|
@ -140,6 +140,8 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
|
||||
kWord64Popcnt = 1u << 15,
|
||||
kWord32ReverseBits = 1u << 16,
|
||||
kWord64ReverseBits = 1u << 17,
|
||||
kWord32ReverseBytes = 1u << 18,
|
||||
kWord64ReverseBytes = 1u << 19,
|
||||
kInt32AbsWithOverflow = 1u << 20,
|
||||
kInt64AbsWithOverflow = 1u << 21,
|
||||
kSpeculationFence = 1u << 22,
|
||||
@ -148,8 +150,9 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
|
||||
kFloat64RoundUp | kFloat32RoundTruncate | kFloat64RoundTruncate |
|
||||
kFloat64RoundTiesAway | kFloat32RoundTiesEven | kFloat64RoundTiesEven |
|
||||
kWord32Ctz | kWord64Ctz | kWord32Popcnt | kWord64Popcnt |
|
||||
kWord32ReverseBits | kWord64ReverseBits | kInt32AbsWithOverflow |
|
||||
kInt64AbsWithOverflow | kSpeculationFence
|
||||
kWord32ReverseBits | kWord64ReverseBits | kWord32ReverseBytes |
|
||||
kWord64ReverseBytes | kInt32AbsWithOverflow | kInt64AbsWithOverflow |
|
||||
kSpeculationFence
|
||||
};
|
||||
typedef base::Flags<Flag, unsigned> Flags;
|
||||
|
||||
@ -235,8 +238,8 @@ class V8_EXPORT_PRIVATE MachineOperatorBuilder final
|
||||
const OptionalOperator Word64Popcnt();
|
||||
const OptionalOperator Word32ReverseBits();
|
||||
const OptionalOperator Word64ReverseBits();
|
||||
const Operator* Word32ReverseBytes();
|
||||
const Operator* Word64ReverseBytes();
|
||||
const OptionalOperator Word32ReverseBytes();
|
||||
const OptionalOperator Word64ReverseBytes();
|
||||
const OptionalOperator Int32AbsWithOverflow();
|
||||
const OptionalOperator Int64AbsWithOverflow();
|
||||
|
||||
|
@ -101,10 +101,8 @@ void MemoryOptimizer::VisitNode(Node* node, AllocationState const* state) {
|
||||
case IrOpcode::kIfException:
|
||||
case IrOpcode::kLoad:
|
||||
case IrOpcode::kProtectedLoad:
|
||||
case IrOpcode::kUnalignedLoad:
|
||||
case IrOpcode::kStore:
|
||||
case IrOpcode::kProtectedStore:
|
||||
case IrOpcode::kUnalignedStore:
|
||||
case IrOpcode::kRetain:
|
||||
case IrOpcode::kUnsafePointerAdd:
|
||||
case IrOpcode::kDebugBreak:
|
||||
|
@ -711,10 +711,10 @@ class V8_EXPORT_PRIVATE RawMachineAssembler {
|
||||
return AddNode(machine()->Float64RoundTiesEven().op(), a);
|
||||
}
|
||||
Node* Word32ReverseBytes(Node* a) {
|
||||
return AddNode(machine()->Word32ReverseBytes(), a);
|
||||
return AddNode(machine()->Word32ReverseBytes().op(), a);
|
||||
}
|
||||
Node* Word64ReverseBytes(Node* a) {
|
||||
return AddNode(machine()->Word64ReverseBytes(), a);
|
||||
return AddNode(machine()->Word64ReverseBytes().op(), a);
|
||||
}
|
||||
|
||||
// Float64 bit operations.
|
||||
|
@ -1070,9 +1070,9 @@ static bool ReverseBytesSupported(MachineOperatorBuilder* m,
|
||||
switch (size_in_bytes) {
|
||||
case 4:
|
||||
case 16:
|
||||
return true;
|
||||
return m->Word32ReverseBytes().IsSupported();
|
||||
case 8:
|
||||
return m->Is64();
|
||||
return m->Word64ReverseBytes().IsSupported();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1137,16 +1137,16 @@ Node* WasmGraphBuilder::BuildChangeEndiannessStore(
|
||||
if (ReverseBytesSupported(m, valueSizeInBytes)) {
|
||||
switch (valueSizeInBytes) {
|
||||
case 4:
|
||||
result = graph()->NewNode(m->Word32ReverseBytes(), value);
|
||||
result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
|
||||
break;
|
||||
case 8:
|
||||
result = graph()->NewNode(m->Word64ReverseBytes(), value);
|
||||
result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
|
||||
break;
|
||||
case 16: {
|
||||
Node* byte_reversed_lanes[4];
|
||||
for (int lane = 0; lane < 4; lane++) {
|
||||
byte_reversed_lanes[lane] = graph()->NewNode(
|
||||
m->Word32ReverseBytes(),
|
||||
m->Word32ReverseBytes().op(),
|
||||
graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
|
||||
value));
|
||||
}
|
||||
@ -1272,21 +1272,21 @@ Node* WasmGraphBuilder::BuildChangeEndiannessLoad(Node* node,
|
||||
switch (valueSizeInBytes) {
|
||||
case 2:
|
||||
result =
|
||||
graph()->NewNode(m->Word32ReverseBytes(),
|
||||
graph()->NewNode(m->Word32ReverseBytes().op(),
|
||||
graph()->NewNode(m->Word32Shl(), value,
|
||||
mcgraph()->Int32Constant(16)));
|
||||
break;
|
||||
case 4:
|
||||
result = graph()->NewNode(m->Word32ReverseBytes(), value);
|
||||
result = graph()->NewNode(m->Word32ReverseBytes().op(), value);
|
||||
break;
|
||||
case 8:
|
||||
result = graph()->NewNode(m->Word64ReverseBytes(), value);
|
||||
result = graph()->NewNode(m->Word64ReverseBytes().op(), value);
|
||||
break;
|
||||
case 16: {
|
||||
Node* byte_reversed_lanes[4];
|
||||
for (int lane = 0; lane < 4; lane++) {
|
||||
byte_reversed_lanes[lane] = graph()->NewNode(
|
||||
m->Word32ReverseBytes(),
|
||||
m->Word32ReverseBytes().op(),
|
||||
graph()->NewNode(mcgraph()->machine()->I32x4ExtractLane(lane),
|
||||
value));
|
||||
}
|
||||
|
@ -1213,12 +1213,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
||||
__ Popcntl(i.OutputRegister(), i.InputOperand(0));
|
||||
}
|
||||
break;
|
||||
case kX64Bswap:
|
||||
__ bswapq(i.OutputRegister());
|
||||
break;
|
||||
case kX64Bswap32:
|
||||
__ bswapl(i.OutputRegister());
|
||||
break;
|
||||
case kSSEFloat32Cmp:
|
||||
ASSEMBLE_SSE_BINOP(Ucomiss);
|
||||
break;
|
||||
|
@ -56,8 +56,6 @@ namespace compiler {
|
||||
V(X64Tzcnt32) \
|
||||
V(X64Popcnt) \
|
||||
V(X64Popcnt32) \
|
||||
V(X64Bswap) \
|
||||
V(X64Bswap32) \
|
||||
V(LFence) \
|
||||
V(SSEFloat32Cmp) \
|
||||
V(SSEFloat32Add) \
|
||||
|
@ -54,8 +54,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
|
||||
case kX64Tzcnt32:
|
||||
case kX64Popcnt:
|
||||
case kX64Popcnt32:
|
||||
case kX64Bswap:
|
||||
case kX64Bswap32:
|
||||
case kSSEFloat32Cmp:
|
||||
case kSSEFloat32Add:
|
||||
case kSSEFloat32Sub:
|
||||
|
@ -794,15 +794,9 @@ void InstructionSelector::VisitWord32ReverseBits(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64ReverseBits(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord64ReverseBytes(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
Emit(kX64Bswap, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)));
|
||||
}
|
||||
void InstructionSelector::VisitWord64ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
Emit(kX64Bswap32, g.DefineSameAsFirst(node), g.UseRegister(node->InputAt(0)));
|
||||
}
|
||||
void InstructionSelector::VisitWord32ReverseBytes(Node* node) { UNREACHABLE(); }
|
||||
|
||||
void InstructionSelector::VisitInt32Add(Node* node) {
|
||||
X64OperandGenerator g(this);
|
||||
|
@ -1409,12 +1409,6 @@ void Assembler::xor_(Operand dst, const Immediate& x) {
|
||||
emit_arith(6, dst, x);
|
||||
}
|
||||
|
||||
void Assembler::bswap(Register dst) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x0F);
|
||||
EMIT(0xC8 + dst.code());
|
||||
}
|
||||
|
||||
void Assembler::bt(Operand dst, Register src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
EMIT(0x0F);
|
||||
|
@ -817,7 +817,6 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void xor_(Operand dst, const Immediate& x);
|
||||
|
||||
// Bit operations.
|
||||
void bswap(Register dst);
|
||||
void bt(Operand dst, Register src);
|
||||
void bts(Register dst, Register src) { bts(Operand(dst), src); }
|
||||
void bts(Operand dst, Register src);
|
||||
|
@ -1749,10 +1749,6 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
|
||||
NameOfXMMRegister(regop),
|
||||
static_cast<int>(imm8));
|
||||
data += 2;
|
||||
} else if (f0byte >= 0xC8 && f0byte <= 0xCF) {
|
||||
// bswap
|
||||
int reg = f0byte - 0xC8;
|
||||
AppendToBuffer("bswap %s", NameOfCPURegister(reg));
|
||||
} else if ((f0byte & 0xF0) == 0x80) {
|
||||
data += JumpConditional(data, branch_hint);
|
||||
} else if (f0byte == 0xBE || f0byte == 0xBF || f0byte == 0xB6 ||
|
||||
|
@ -929,20 +929,6 @@ void Assembler::shift(Operand dst, int subcode, int size) {
|
||||
emit_operand(subcode, dst);
|
||||
}
|
||||
|
||||
void Assembler::bswapl(Register dst) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_32(dst);
|
||||
emit(0x0F);
|
||||
emit(0xC8 + dst.low_bits());
|
||||
}
|
||||
|
||||
void Assembler::bswapq(Register dst) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_64(dst);
|
||||
emit(0x0F);
|
||||
emit(0xC8 + dst.low_bits());
|
||||
}
|
||||
|
||||
void Assembler::bt(Operand dst, Register src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_64(src, dst);
|
||||
|
@ -879,8 +879,6 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void testw(Operand op, Register reg);
|
||||
|
||||
// Bit operations.
|
||||
void bswapl(Register dst);
|
||||
void bswapq(Register dst);
|
||||
void bt(Operand dst, Register src);
|
||||
void bts(Operand dst, Register src);
|
||||
void bsrq(Register dst, Register src);
|
||||
|
@ -2172,10 +2172,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
|
||||
current += PrintRightXMMOperand(current);
|
||||
AppendToBuffer(", %d", (*current) & 3);
|
||||
current += 1;
|
||||
} else if (opcode >= 0xC8 && opcode <= 0xCF) {
|
||||
// bswap
|
||||
int reg = (opcode - 0xC8) | (rex_r() ? 8 : 0);
|
||||
AppendToBuffer("bswap%c %s", operand_size_code(), NameOfCPURegister(reg));
|
||||
} else if (opcode == 0x50) {
|
||||
// movmskps reg, xmm
|
||||
int mod, regop, rm;
|
||||
@ -2241,7 +2237,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
|
||||
// The argument is the second byte of the two-byte opcode.
|
||||
// Returns nullptr if the instruction is not handled here.
|
||||
const char* DisassemblerX64::TwoByteMnemonic(byte opcode) {
|
||||
if (opcode >= 0xC8 && opcode <= 0xCF) return "bswap";
|
||||
switch (opcode) {
|
||||
case 0x1F:
|
||||
return "nop";
|
||||
|
@ -85,7 +85,11 @@ TEST(RunWord32ReverseBits) {
|
||||
|
||||
TEST(RunWord32ReverseBytes) {
|
||||
BufferedRawMachineAssemblerTester<uint32_t> m(MachineType::Uint32());
|
||||
m.Return(m.AddNode(m.machine()->Word32ReverseBytes(), m.Parameter(0)));
|
||||
if (!m.machine()->Word32ReverseBytes().IsSupported()) {
|
||||
// We can only test the operator if it exists on the testing platform.
|
||||
return;
|
||||
}
|
||||
m.Return(m.AddNode(m.machine()->Word32ReverseBytes().op(), m.Parameter(0)));
|
||||
|
||||
CHECK_EQ(uint32_t(0x00000000), m.Call(uint32_t(0x00000000)));
|
||||
CHECK_EQ(uint32_t(0x12345678), m.Call(uint32_t(0x78563412)));
|
||||
@ -220,7 +224,11 @@ TEST(RunWord64ReverseBits) {
|
||||
|
||||
TEST(RunWord64ReverseBytes) {
|
||||
BufferedRawMachineAssemblerTester<uint64_t> m(MachineType::Uint64());
|
||||
m.Return(m.AddNode(m.machine()->Word64ReverseBytes(), m.Parameter(0)));
|
||||
if (!m.machine()->Word64ReverseBytes().IsSupported()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m.Return(m.AddNode(m.machine()->Word64ReverseBytes().op(), m.Parameter(0)));
|
||||
|
||||
CHECK_EQ(uint64_t(0x0000000000000000), m.Call(uint64_t(0x0000000000000000)));
|
||||
CHECK_EQ(uint64_t(0x1234567890ABCDEF), m.Call(uint64_t(0xEFCDAB9078563412)));
|
||||
|
@ -483,9 +483,6 @@ TEST(Type3) {
|
||||
|
||||
COMPARE(rbit(r1, r2), "e6ff1f32 rbit r1, r2");
|
||||
COMPARE(rbit(r10, ip), "e6ffaf3c rbit r10, ip");
|
||||
|
||||
COMPARE(rev(r1, r2), "e6bf1f32 rev r1, r2");
|
||||
COMPARE(rev(r10, ip), "e6bfaf3c rev r10, ip");
|
||||
}
|
||||
|
||||
COMPARE(usat(r0, 1, Operand(r1)),
|
||||
|
@ -91,8 +91,6 @@ TEST(DisasmIa320) {
|
||||
__ add(edi, Operand(ebp, ecx, times_4, -3999));
|
||||
__ add(Operand(ebp, ecx, times_4, 12), Immediate(12));
|
||||
|
||||
__ bswap(eax);
|
||||
|
||||
__ nop();
|
||||
__ add(ebx, Immediate(12));
|
||||
__ nop();
|
||||
|
@ -89,8 +89,6 @@ TEST(DisasmX64) {
|
||||
__ addq(rdi, Operand(rbp, rcx, times_4, -3999));
|
||||
__ addq(Operand(rbp, rcx, times_4, 12), Immediate(12));
|
||||
|
||||
__ bswapl(rax);
|
||||
__ bswapq(rdi);
|
||||
__ bsrl(rax, r15);
|
||||
__ bsrl(r9, Operand(rcx, times_8, 91919));
|
||||
|
||||
|
@ -882,7 +882,7 @@ TEST_F(Int64LoweringTest, I64PhiWord32) {
|
||||
}
|
||||
|
||||
TEST_F(Int64LoweringTest, I64ReverseBytes) {
|
||||
LowerGraph(graph()->NewNode(machine()->Word64ReverseBytes(),
|
||||
LowerGraph(graph()->NewNode(machine()->Word64ReverseBytes().placeholder(),
|
||||
Int64Constant(value(0))),
|
||||
MachineRepresentation::kWord64);
|
||||
EXPECT_THAT(
|
||||
|
Loading…
Reference in New Issue
Block a user