1 // Copyright 2022 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_COMPILER_SIMPLIFIED_LOWERING_VERIFIER_H_ 6 #define V8_COMPILER_SIMPLIFIED_LOWERING_VERIFIER_H_ 7 8 #include "src/compiler/representation-change.h" 9 10 namespace v8 { 11 namespace internal { 12 namespace compiler { 13 14 class OperationTyper; 15 16 class SimplifiedLoweringVerifier final { 17 public: 18 struct PerNodeData { 19 base::Optional<Type> type = base::nullopt; 20 Truncation truncation = Truncation::Any(IdentifyZeros::kDistinguishZeros); 21 }; 22 SimplifiedLoweringVerifier(Zone * zone,Graph * graph)23 SimplifiedLoweringVerifier(Zone* zone, Graph* graph) 24 : hints_(zone), data_(zone), graph_(graph) {} 25 26 void VisitNode(Node* node, OperationTyper& op_typer); 27 RecordHint(Node * node)28 void RecordHint(Node* node) { 29 DCHECK_EQ(node->opcode(), IrOpcode::kSLVerifierHint); 30 hints_.push_back(node); 31 } inserted_hints()32 const ZoneVector<Node*>& inserted_hints() const { return hints_; } 33 GetType(Node * node)34 base::Optional<Type> GetType(Node* node) const { 35 if (NodeProperties::IsTyped(node)) { 36 return NodeProperties::GetType(node); 37 } 38 // For nodes that have not been typed before SL, we use the type that has 39 // been inferred by the verifier. 40 if (node->id() < data_.size()) { 41 return data_[node->id()].type; 42 } 43 return base::nullopt; 44 } 45 46 private: ResizeDataIfNecessary(Node * node)47 void ResizeDataIfNecessary(Node* node) { 48 if (data_.size() <= node->id()) { 49 data_.resize(node->id() + 1); 50 } 51 DCHECK_EQ(data_[node->id()].truncation, 52 Truncation::Any(IdentifyZeros::kDistinguishZeros)); 53 } 54 SetType(Node * node,const Type & type)55 void SetType(Node* node, const Type& type) { 56 ResizeDataIfNecessary(node); 57 data_[node->id()].type = type; 58 } 59 InputType(Node * node,int input_index)60 Type InputType(Node* node, int input_index) const { 61 // TODO(nicohartmann): Check that inputs are typed, once all operators are 62 // supported. 63 Node* input = node->InputAt(input_index); 64 if (NodeProperties::IsTyped(input)) { 65 return NodeProperties::GetType(input); 66 } 67 // For nodes that have not been typed before SL, we use the type that has 68 // been inferred by the verifier. 69 base::Optional<Type> type_opt; 70 if (input->id() < data_.size()) { 71 type_opt = data_[input->id()].type; 72 } 73 return type_opt.has_value() ? *type_opt : Type::None(); 74 } 75 SetTruncation(Node * node,const Truncation & truncation)76 void SetTruncation(Node* node, const Truncation& truncation) { 77 ResizeDataIfNecessary(node); 78 data_[node->id()].truncation = truncation; 79 } 80 InputTruncation(Node * node,int input_index)81 Truncation InputTruncation(Node* node, int input_index) const { 82 static const Truncation any_truncation = 83 Truncation::Any(IdentifyZeros::kDistinguishZeros); 84 85 Node* input = node->InputAt(input_index); 86 if (input->id() < data_.size()) { 87 return data_[input->id()].truncation; 88 } 89 return any_truncation; 90 } 91 92 void CheckType(Node* node, const Type& type); 93 void CheckAndSet(Node* node, const Type& type, const Truncation& trunc); 94 95 // Generalize to a less strict truncation in the context of a given type. For 96 // example, a Truncation::kWord32[kIdentifyZeros] does not have any effect on 97 // a type Range(0, 100), because all equivalence classes are singleton, for 98 // the values of the given type. We can use Truncation::Any[kDistinguishZeros] 99 // instead to avoid a combinatorial explosion of occurring type-truncation- 100 // pairs. 101 Truncation GeneralizeTruncation(const Truncation& truncation, 102 const Type& type) const; 103 graph_zone()104 Zone* graph_zone() const { return graph_->zone(); } 105 106 ZoneVector<Node*> hints_; 107 ZoneVector<PerNodeData> data_; 108 Graph* graph_; 109 }; 110 111 } // namespace compiler 112 } // namespace internal 113 } // namespace v8 114 115 #endif // V8_COMPILER_SIMPLIFIED_LOWERING_VERIFIER_H_ 116