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:
Leszek Swirski 2018-08-14 08:23:06 +00:00 committed by Commit Bot
parent 3e545e4045
commit 6a62d88e9b
43 changed files with 355 additions and 271 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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());

View File

@ -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.

View File

@ -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());

View File

@ -46,7 +46,6 @@ namespace compiler {
V(ArmUxth) \
V(ArmUxtab) \
V(ArmRbit) \
V(ArmRev) \
V(ArmUxtah) \
V(ArmAddPair) \
V(ArmSubPair) \

View File

@ -49,7 +49,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArmUxtab:
case kArmUxtah:
case kArmRbit:
case kArmRev:
case kArmAddPair:
case kArmSubPair:
case kArmMulPair:

View File

@ -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(); }

View File

@ -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;

View File

@ -77,8 +77,6 @@ namespace compiler {
V(Arm64Bfi) \
V(Arm64Rbit) \
V(Arm64Rbit32) \
V(Arm64Rev) \
V(Arm64Rev32) \
V(Arm64TestAndBranch32) \
V(Arm64TestAndBranch) \
V(Arm64CompareAndBranch32) \

View File

@ -79,8 +79,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kArm64Bfi:
case kArm64Rbit:
case kArm64Rbit32:
case kArm64Rev:
case kArm64Rev32:
case kArm64Float32Cmp:
case kArm64Float32Add:
case kArm64Float32Sub:

View File

@ -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(); }

View File

@ -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);

View File

@ -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);

View File

@ -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_);

View File

@ -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);

View File

@ -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);

View File

@ -43,7 +43,6 @@ namespace compiler {
V(IA32Lzcnt) \
V(IA32Tzcnt) \
V(IA32Popcnt) \
V(IA32Bswap) \
V(LFence) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \

View File

@ -43,7 +43,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kIA32Lzcnt:
case kIA32Tzcnt:
case kIA32Popcnt:
case kIA32Bswap:
case kIA32Lea:
case kSSEFloat32Cmp:
case kSSEFloat32Add:

View File

@ -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);

View File

@ -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;
}

View File

@ -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) \

View File

@ -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();

View File

@ -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:

View File

@ -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.

View File

@ -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));
}

View File

@ -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;

View File

@ -56,8 +56,6 @@ namespace compiler {
V(X64Tzcnt32) \
V(X64Popcnt) \
V(X64Popcnt32) \
V(X64Bswap) \
V(X64Bswap32) \
V(LFence) \
V(SSEFloat32Cmp) \
V(SSEFloat32Add) \

View File

@ -54,8 +54,6 @@ int InstructionScheduler::GetTargetInstructionFlags(
case kX64Tzcnt32:
case kX64Popcnt:
case kX64Popcnt32:
case kX64Bswap:
case kX64Bswap32:
case kSSEFloat32Cmp:
case kSSEFloat32Add:
case kSSEFloat32Sub:

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 ||

View File

@ -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);

View File

@ -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);

View File

@ -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";

View File

@ -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)));

View File

@ -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)),

View File

@ -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();

View File

@ -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));

View File

@ -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(