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

Unified Diff: src/compiler/simplified-lowering.cc

Issue 1473733007: [turbofan] Checking monotonicity of representation inference outputs and inputs. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Tweaks Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/representation-change.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/simplified-lowering.cc
diff --git a/src/compiler/simplified-lowering.cc b/src/compiler/simplified-lowering.cc
index 0cc18584f70b694a1d4b72b42befbe2bb39a6f66..9d00d44e329a39d0e60ebd22722a85d33ef81b72 100644
--- a/src/compiler/simplified-lowering.cc
+++ b/src/compiler/simplified-lowering.cc
@@ -154,6 +154,102 @@ UseInfo UseInfoForBasePointer(const ElementAccess& access) {
return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt();
}
+
+#ifdef DEBUG
+// Helpers for monotonicity checking.
+
+bool MachineTypeIsSubtype(MachineType t1, MachineType t2) {
+ switch (t1) {
+ case kMachNone:
+ return true;
+ case kTypeBool:
+ return t2 == kTypeBool || t2 == kTypeNumber || t2 == kTypeAny;
+ case kTypeInt32:
+ return t2 == kTypeInt32 || t2 == kTypeNumber || t2 == kTypeAny;
+ case kTypeUint32:
+ return t2 == kTypeUint32 || t2 == kTypeNumber || t2 == kTypeAny;
+ case kTypeInt64:
+ return t2 == kTypeInt64;
+ case kTypeUint64:
+ return t2 == kTypeUint64;
+ case kTypeNumber:
+ return t2 == kTypeNumber || t2 == kTypeAny;
+ case kTypeAny:
+ return t2 == kTypeAny;
+ default:
+ break;
+ }
+ UNREACHABLE();
+ return false;
+}
+
+
+bool MachineRepresentationIsSubtype(MachineType r1, MachineType r2) {
+ switch (r1) {
+ case kMachNone:
+ return true;
+ case kRepBit:
+ return r2 == kRepBit || r2 == kRepTagged;
+ case kRepWord8:
+ return r2 == kRepWord8 || r2 == kRepWord16 || r2 == kRepWord32 ||
+ r2 == kRepWord64 || r2 == kRepFloat32 || r2 == kRepFloat64 ||
+ r2 == kRepTagged;
+ case kRepWord16:
+ return r2 == kRepWord16 || r2 == kRepWord32 || r2 == kRepWord64 ||
+ r2 == kRepFloat32 || r2 == kRepFloat64 || r2 == kRepTagged;
+ case kRepWord32:
+ return r2 == kRepWord32 || r2 == kRepWord64 || r2 == kRepFloat64 ||
+ r2 == kRepTagged;
+ case kRepWord64:
+ return r2 == kRepWord64;
+ case kRepFloat32:
+ return r2 == kRepFloat32 || r2 == kRepFloat64 || r2 == kRepTagged;
+ case kRepFloat64:
+ return r2 == kRepFloat64 || r2 == kRepTagged;
+ case kRepTagged:
+ return r2 == kRepTagged;
+ default:
+ break;
+ }
+ UNREACHABLE();
+ return false;
+}
+
+
+bool MachineTypeRepIsSubtype(MachineTypeUnion m1, MachineTypeUnion m2) {
+ return MachineTypeIsSubtype(static_cast<MachineType>(m1 & kTypeMask),
+ static_cast<MachineType>(m2 & kTypeMask)) &&
+ MachineRepresentationIsSubtype(
+ static_cast<MachineType>(m1 & kRepMask),
+ static_cast<MachineType>(m2 & kRepMask));
+}
+
+
+class InputUseInfos {
+ public:
+ explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {}
+
+ void SetAndCheckInput(Node* node, int index, UseInfo use_info) {
+ if (input_use_infos_.empty()) {
+ input_use_infos_.resize(node->InputCount(), UseInfo::None());
+ }
+ // Check that the new use informatin is a super-type of the old
+ // one.
+ CHECK(IsUseLessGeneral(input_use_infos_[index], use_info));
+ input_use_infos_[index] = use_info;
+ }
+
+ private:
+ ZoneVector<UseInfo> input_use_infos_;
+
+ static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) {
+ return MachineRepresentationIsSubtype(use1.preferred(), use2.preferred()) &&
+ use1.truncation().IsLessGeneralThan(use2.truncation());
+ }
+};
+
+#endif // DEBUG
+
} // namespace
@@ -191,19 +287,23 @@ class RepresentationSelector {
: jsgraph_(jsgraph),
count_(jsgraph->graph()->NodeCount()),
info_(count_, zone),
+#ifdef DEBUG
+ node_input_use_infos_(count_, InputUseInfos(zone), zone),
+#endif
nodes_(zone),
replacements_(zone),
phase_(PROPAGATE),
changer_(changer),
queue_(zone),
source_positions_(source_positions),
- type_cache_(TypeCache::Get()) {}
+ type_cache_(TypeCache::Get()) {
+ }
void Run(SimplifiedLowering* lowering) {
// Run propagation phase to a fixpoint.
TRACE("--{Propagation phase}--\n");
phase_ = PROPAGATE;
- Enqueue(jsgraph_->graph()->end());
+ EnqueueInitial(jsgraph_->graph()->end());
// Process nodes from the queue until it is empty.
while (!queue_.empty()) {
Node* node = queue_.front();
@@ -245,11 +345,27 @@ class RepresentationSelector {
}
}
- // Enqueue {node} if the {use} contains new information for that node.
- // Add {node} to {nodes_} if this is the first time it's been visited.
- void Enqueue(Node* node, UseInfo use_info = UseInfo::None()) {
+ void EnqueueInitial(Node* node) {
+ NodeInfo* info = GetInfo(node);
+ info->set_visited();
+ info->set_queued(true);
+ nodes_.push_back(node);
+ queue_.push(node);
+ }
+
+ // Enqueue {use_node}'s {index} input if the {use} contains new information
+ // for that input node. Add the input to {nodes_} if this is the first time
+ // it's been visited.
+ void EnqueueInput(Node* use_node, int index,
+ UseInfo use_info = UseInfo::None()) {
+ Node* node = use_node->InputAt(index);
if (phase_ != PROPAGATE) return;
NodeInfo* info = GetInfo(node);
+#ifdef DEBUG
+ // Check monotonicity of input requirements.
+ node_input_use_infos_[use_node->id()].SetAndCheckInput(use_node, index,
+ use_info);
+#endif // DEBUG
if (!info->visited()) {
// First visit of this node.
info->set_visited();
@@ -284,7 +400,9 @@ class RepresentationSelector {
// instruction.
DCHECK((output & kRepMask) == 0 ||
base::bits::IsPowerOfTwo32(output & kRepMask));
- GetInfo(node)->set_output_type(output);
+ NodeInfo* info = GetInfo(node);
+ DCHECK(MachineTypeRepIsSubtype(info->output_type(), output));
+ info->set_output_type(output);
}
bool BothInputsAre(Node* node, Type* type) {
@@ -293,10 +411,6 @@ class RepresentationSelector {
NodeProperties::GetType(node->InputAt(1))->Is(type);
}
- void EnqueueInputUse(Node* node, int index, UseInfo use) {
- Enqueue(node->InputAt(index), use);
- }
-
void ConvertInput(Node* node, int index, UseInfo use) {
Node* input = node->InputAt(index);
// In the change phase, insert a change before the use if necessary.
@@ -320,7 +434,7 @@ class RepresentationSelector {
void ProcessInput(Node* node, int index, UseInfo use) {
if (phase_ == PROPAGATE) {
- EnqueueInputUse(node, index, use);
+ EnqueueInput(node, index, use);
} else {
ConvertInput(node, index, use);
}
@@ -331,11 +445,11 @@ class RepresentationSelector {
DCHECK_GE(index, NodeProperties::PastContextIndex(node));
for (int i = std::max(index, NodeProperties::FirstEffectIndex(node));
i < NodeProperties::PastEffectIndex(node); ++i) {
- Enqueue(node->InputAt(i)); // Effect inputs: just visit
+ EnqueueInput(node, i); // Effect inputs: just visit
}
for (int i = std::max(index, NodeProperties::FirstControlIndex(node));
i < NodeProperties::PastControlIndex(node); ++i) {
- Enqueue(node->InputAt(i)); // Control inputs: just visit
+ EnqueueInput(node, i); // Control inputs: just visit
}
}
@@ -352,10 +466,8 @@ class RepresentationSelector {
}
// Only enqueue other inputs (framestates, effects, control).
for (int i = tagged_count; i < node->InputCount(); i++) {
- Enqueue(node->InputAt(i));
+ EnqueueInput(node, i);
}
- // Assume the output is tagged.
- SetOutput(node, kMachAnyTagged);
}
// Helper for binops of the R x L -> O variety.
@@ -365,7 +477,7 @@ class RepresentationSelector {
ProcessInput(node, 0, left_use);
ProcessInput(node, 1, right_use);
for (int i = 2; i < node->InputCount(); i++) {
- Enqueue(node->InputAt(i));
+ EnqueueInput(node, i);
}
SetOutput(node, output);
}
@@ -523,7 +635,7 @@ class RepresentationSelector {
void VisitStateValues(Node* node) {
if (phase_ == PROPAGATE) {
for (int i = 0; i < node->InputCount(); i++) {
- Enqueue(node->InputAt(i), UseInfo::Any());
+ EnqueueInput(node, i, UseInfo::Any());
}
} else {
Zone* zone = jsgraph_->zone();
@@ -613,11 +725,11 @@ class RepresentationSelector {
case IrOpcode::kBranch:
ProcessInput(node, 0, UseInfo::Bool());
- Enqueue(NodeProperties::GetControlInput(node, 0));
+ EnqueueInput(node, NodeProperties::FirstControlIndex(node));
break;
case IrOpcode::kSwitch:
ProcessInput(node, 0, UseInfo::TruncatingWord32());
- Enqueue(NodeProperties::GetControlInput(node, 0));
+ EnqueueInput(node, NodeProperties::FirstControlIndex(node));
break;
case IrOpcode::kSelect:
return VisitSelect(node, truncation, lowering);
@@ -1104,6 +1216,8 @@ class RepresentationSelector {
break;
default:
VisitInputs(node);
+ // Assume the output is tagged.
+ SetOutput(node, kMachAnyTagged);
break;
}
}
@@ -1154,6 +1268,10 @@ class RepresentationSelector {
JSGraph* jsgraph_;
size_t const count_; // number of nodes in the graph
ZoneVector<NodeInfo> info_; // node id -> usage information
+#ifdef DEBUG
+ ZoneVector<InputUseInfos> node_input_use_infos_; // Debug information about
+ // requirements on inputs.
+#endif // DEBUG
NodeVector nodes_; // collected nodes
NodeVector replacements_; // replacements to be done after lowering
Phase phase_; // current phase of algorithm
« no previous file with comments | « src/compiler/representation-change.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698