[ptr-compr] Generate TaggedEqual as Word32Equal of compressed values

... in both CSA code and TurboFan. This is a prerequisite for smi-corrupting
decompression.

The decompression eliminator changes is a workaround to ensure that the result
of comparisons of two constant Smis is still a constexpr (the failing test is
cctest/test-torque/TestLoadEliminationFixed). Better optimizations will be
landed in a follow-up CLs.

Bug: v8:9706
Change-Id: Ie2d90f6a7714aa749439e3f457d90d663d0efe49
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1815133
Reviewed-by: Santiago Aboy Solanes <solanes@chromium.org>
Reviewed-by: Georg Neis <neis@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63991}
This commit is contained in:
Igor Sheludko 2019-09-25 14:14:00 +02:00 committed by Commit Bot
parent 53780c06b7
commit 4ce267a832
8 changed files with 60 additions and 4 deletions

View File

@ -295,7 +295,9 @@ void TurboAssembler::Mov(const Register& rd, const Operand& operand,
} else if (RelocInfo::IsEmbeddedObjectMode(operand.ImmediateRMode())) {
Handle<HeapObject> x(
reinterpret_cast<Address*>(operand.ImmediateValue()));
IndirectLoadConstant(rd, x);
// TODO(v8:9706): Fix-it! This load will always uncompress the value
// even when we are loading a compressed embedded object.
IndirectLoadConstant(rd.X(), x);
return;
}
}

View File

@ -510,9 +510,12 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
uintptr_t ConstexprWordNot(uintptr_t a) { return ~a; }
TNode<BoolT> TaggedEqual(TNode<AnyTaggedT> a, TNode<AnyTaggedT> b) {
// In pointer-compressed architectures, the instruction selector will narrow
// this comparison to a 32-bit one.
#ifdef V8_COMPRESS_POINTERS
return Word32Equal(ChangeTaggedToCompressed(a),
ChangeTaggedToCompressed(b));
#else
return WordEqual(ReinterpretCast<WordT>(a), ReinterpretCast<WordT>(b));
#endif
}
TNode<BoolT> TaggedNotEqual(TNode<AnyTaggedT> a, TNode<AnyTaggedT> b) {

View File

@ -1461,6 +1461,8 @@ void TurboAssembler::Move(Register result, Handle<HeapObject> object,
RelocInfo::Mode rmode) {
if (FLAG_embedded_builtins) {
if (root_array_available_ && options().isolate_independent_code) {
// TODO(v8:9706): Fix-it! This load will always uncompress the value
// even when we are loading a compressed embedded object.
IndirectLoadConstant(result, object);
return;
}

View File

@ -302,6 +302,7 @@ TNode<Float64T> Float64Add(TNode<Float64T> a, TNode<Float64T> b);
V(ChangeInt32ToInt64, Int64T, Int32T) \
V(ChangeUint32ToFloat64, Float64T, Word32T) \
V(ChangeUint32ToUint64, Uint64T, Word32T) \
V(ChangeTaggedToCompressed, TaggedT, AnyTaggedT) \
V(BitcastInt32ToFloat32, Float32T, Word32T) \
V(BitcastFloat32ToInt32, Uint32T, Float32T) \
V(RoundFloat64ToInt32, Int32T, Float64T) \

View File

@ -167,6 +167,42 @@ Reduction DecompressionElimination::ReduceTypedStateValues(Node* node) {
return any_change ? Changed(node) : NoChange();
}
Reduction DecompressionElimination::ReduceWord32Equal(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kWord32Equal);
DCHECK_EQ(node->InputCount(), 2);
Node* lhs = node->InputAt(0);
Node* rhs = node->InputAt(1);
if (!IrOpcode::IsCompressOpcode(lhs->opcode()) ||
!IrOpcode::IsCompressOpcode(rhs->opcode())) {
return NoChange();
}
// Input nodes for compress operation.
lhs = lhs->InputAt(0);
rhs = rhs->InputAt(0);
bool changed = false;
if (lhs->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
Node* input = lhs->InputAt(0);
if (IsReducibleConstantOpcode(input->opcode())) {
node->ReplaceInput(0, GetCompressedConstant(input));
changed = true;
}
}
if (rhs->opcode() == IrOpcode::kBitcastWordToTaggedSigned) {
Node* input = rhs->InputAt(0);
if (IsReducibleConstantOpcode(input->opcode())) {
node->ReplaceInput(1, GetCompressedConstant(input));
changed = true;
}
}
return changed ? Changed(node) : NoChange();
}
Reduction DecompressionElimination::ReduceWord64Equal(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kWord64Equal);
@ -220,6 +256,8 @@ Reduction DecompressionElimination::Reduce(Node* node) {
return ReducePhi(node);
case IrOpcode::kTypedStateValues:
return ReduceTypedStateValues(node);
case IrOpcode::kWord32Equal:
return ReduceWord32Equal(node);
case IrOpcode::kWord64Equal:
return ReduceWord64Equal(node);
default:

View File

@ -65,6 +65,11 @@ class V8_EXPORT_PRIVATE DecompressionElimination final
// value of that constant.
Reduction ReduceWord64Equal(Node* node);
// This is a workaround for load elimination test.
// Replaces Compress -> BitcastWordToTaggedSigned -> ReducibleConstant
// to CompressedConstant on both inputs of Word32Equal operation.
Reduction ReduceWord32Equal(Node* node);
Graph* graph() const { return graph_; }
MachineOperatorBuilder* machine() const { return machine_; }
CommonOperatorBuilder* common() const { return common_; }

View File

@ -99,7 +99,12 @@ Node* GraphAssembler::IntPtrEqual(Node* left, Node* right) {
}
Node* GraphAssembler::TaggedEqual(Node* left, Node* right) {
#ifdef V8_COMPRESS_POINTERS
return Word32Equal(ChangeTaggedToCompressed(left),
ChangeTaggedToCompressed(right));
#else
return WordEqual(left, right);
#endif
}
Node* GraphAssembler::Float64RoundDown(Node* value) {

View File

@ -461,7 +461,7 @@ class MachineRepresentationChecker {
CheckValueInputForFloat64Op(node, 0);
break;
case IrOpcode::kWord64Equal:
if (Is64()) {
if (Is64() && !COMPRESS_POINTERS_BOOL) {
CheckValueInputIsTaggedOrPointer(node, 0);
CheckValueInputIsTaggedOrPointer(node, 1);
if (!is_stub_) {