blob: 8ac8e7b2aa94d4eaccc8ad71e79c175b05e5c58a [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2014 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_INSTRUCTION_SELECTOR_H_
6#define V8_COMPILER_INSTRUCTION_SELECTOR_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include <map>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009
10#include "src/compiler/common-operator.h"
11#include "src/compiler/instruction.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000012#include "src/compiler/instruction-scheduler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000013#include "src/compiler/machine-operator.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000014#include "src/compiler/node.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000015#include "src/zone-containers.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21// Forward declarations.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000022class BasicBlock;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000023struct CallBuffer; // TODO(bmeurer): Remove this.
24class FlagsContinuation;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040025class Linkage;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000026class OperandGenerator;
27struct SwitchInfo;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029// This struct connects nodes of parameters which are going to be pushed on the
30// call stack with their parameter index in the call descriptor of the callee.
31class PushParameter {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033 PushParameter() : node_(nullptr), type_(MachineType::None()) {}
34 PushParameter(Node* node, MachineType type) : node_(node), type_(type) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -040035
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000036 Node* node() const { return node_; }
37 MachineType type() const { return type_; }
38
39 private:
40 Node* node_;
41 MachineType type_;
42};
43
44// Instruction selection generates an InstructionSequence for a given Schedule.
45class InstructionSelector final {
46 public:
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 // Forward declarations.
48 class Features;
49
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 enum SourcePositionMode { kCallSourcePositions, kAllSourcePositions };
51
52 InstructionSelector(
53 Zone* zone, size_t node_count, Linkage* linkage,
54 InstructionSequence* sequence, Schedule* schedule,
Ben Murdoch097c5b22016-05-18 11:27:45 +010055 SourcePositionTable* source_positions, Frame* frame,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 SourcePositionMode source_position_mode = kCallSourcePositions,
57 Features features = SupportedFeatures());
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058
59 // Visit code for the entire graph with the included schedule.
60 void SelectInstructions();
61
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000062 void StartBlock(RpoNumber rpo);
63 void EndBlock(RpoNumber rpo);
64 void AddInstruction(Instruction* instr);
65
Ben Murdochb8a8cc12014-11-26 15:28:44 +000066 // ===========================================================================
67 // ============= Architecture-independent code emission methods. =============
68 // ===========================================================================
69
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000070 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
71 size_t temp_count = 0, InstructionOperand* temps = nullptr);
72 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
73 InstructionOperand a, size_t temp_count = 0,
74 InstructionOperand* temps = nullptr);
75 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
76 InstructionOperand a, InstructionOperand b,
77 size_t temp_count = 0, InstructionOperand* temps = nullptr);
78 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
79 InstructionOperand a, InstructionOperand b,
80 InstructionOperand c, size_t temp_count = 0,
81 InstructionOperand* temps = nullptr);
82 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
83 InstructionOperand a, InstructionOperand b,
84 InstructionOperand c, InstructionOperand d,
85 size_t temp_count = 0, InstructionOperand* temps = nullptr);
86 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
87 InstructionOperand a, InstructionOperand b,
88 InstructionOperand c, InstructionOperand d,
89 InstructionOperand e, size_t temp_count = 0,
90 InstructionOperand* temps = nullptr);
91 Instruction* Emit(InstructionCode opcode, InstructionOperand output,
92 InstructionOperand a, InstructionOperand b,
93 InstructionOperand c, InstructionOperand d,
94 InstructionOperand e, InstructionOperand f,
95 size_t temp_count = 0, InstructionOperand* temps = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 Instruction* Emit(InstructionCode opcode, size_t output_count,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097 InstructionOperand* outputs, size_t input_count,
98 InstructionOperand* inputs, size_t temp_count = 0,
99 InstructionOperand* temps = nullptr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 Instruction* Emit(Instruction* instr);
101
102 // ===========================================================================
Ben Murdochda12d292016-06-02 14:46:10 +0100103 // ===== Architecture-independent deoptimization exit emission methods. ======
104 // ===========================================================================
105
106 Instruction* EmitDeoptimize(InstructionCode opcode, InstructionOperand output,
107 InstructionOperand a, InstructionOperand b,
108 Node* frame_state);
109 Instruction* EmitDeoptimize(InstructionCode opcode, size_t output_count,
110 InstructionOperand* outputs, size_t input_count,
111 InstructionOperand* inputs, Node* frame_state);
112
113 // ===========================================================================
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000114 // ============== Architecture-independent CPU feature methods. ==============
115 // ===========================================================================
116
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117 class Features final {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 public:
119 Features() : bits_(0) {}
120 explicit Features(unsigned bits) : bits_(bits) {}
121 explicit Features(CpuFeature f) : bits_(1u << f) {}
122 Features(CpuFeature f1, CpuFeature f2) : bits_((1u << f1) | (1u << f2)) {}
123
124 bool Contains(CpuFeature f) const { return (bits_ & (1u << f)); }
125
126 private:
127 unsigned bits_;
128 };
129
130 bool IsSupported(CpuFeature feature) const {
131 return features_.Contains(feature);
132 }
133
134 // Returns the features supported on the target platform.
135 static Features SupportedFeatures() {
136 return Features(CpuFeatures::SupportedFeatures());
137 }
138
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400139 // TODO(sigurds) This should take a CpuFeatures argument.
140 static MachineOperatorBuilder::Flags SupportedMachineOperatorFlags();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000141
Ben Murdoch61f157c2016-09-16 13:49:30 +0100142 static MachineOperatorBuilder::AlignmentRequirements AlignmentRequirements();
143
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 // ===========================================================================
145 // ============ Architecture-independent graph covering methods. =============
146 // ===========================================================================
147
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 // Used in pattern matching during code generation.
149 // Check if {node} can be covered while generating code for the current
150 // instruction. A node can be covered if the {user} of the node has the only
151 // edge and the two are in the same basic block.
152 bool CanCover(Node* user, Node* node) const;
153
154 // Checks if {node} was already defined, and therefore code was already
155 // generated for it.
156 bool IsDefined(Node* node) const;
157
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 // Checks if {node} has any uses, and therefore code has to be generated for
159 // it.
160 bool IsUsed(Node* node) const;
161
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400162 // Checks if {node} is currently live.
163 bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node); }
164
Ben Murdoch097c5b22016-05-18 11:27:45 +0100165 // Gets the effect level of {node}.
166 int GetEffectLevel(Node* node) const;
167
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400168 int GetVirtualRegister(const Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 const std::map<NodeId, int> GetVirtualRegistersForTesting() const;
170
171 Isolate* isolate() const { return sequence()->isolate(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400172
173 private:
174 friend class OperandGenerator;
175
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000176 void EmitTableSwitch(const SwitchInfo& sw, InstructionOperand& index_operand);
177 void EmitLookupSwitch(const SwitchInfo& sw,
178 InstructionOperand& value_operand);
179
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400180 // Inform the instruction selection that {node} was just defined.
181 void MarkAsDefined(Node* node);
182
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 // Inform the instruction selection that {node} has at least one use and we
184 // will need to generate code for it.
185 void MarkAsUsed(Node* node);
186
Ben Murdoch097c5b22016-05-18 11:27:45 +0100187 // Sets the effect level of {node}.
188 void SetEffectLevel(Node* node, int effect_level);
189
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000190 // Inform the register allocation of the representation of the value produced
191 // by {node}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000192 void MarkAsRepresentation(MachineRepresentation rep, Node* node);
193 void MarkAsWord32(Node* node) {
194 MarkAsRepresentation(MachineRepresentation::kWord32, node);
195 }
196 void MarkAsWord64(Node* node) {
197 MarkAsRepresentation(MachineRepresentation::kWord64, node);
198 }
199 void MarkAsFloat32(Node* node) {
200 MarkAsRepresentation(MachineRepresentation::kFloat32, node);
201 }
202 void MarkAsFloat64(Node* node) {
203 MarkAsRepresentation(MachineRepresentation::kFloat64, node);
204 }
205 void MarkAsReference(Node* node) {
206 MarkAsRepresentation(MachineRepresentation::kTagged, node);
207 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209 // Inform the register allocation of the representation of the unallocated
210 // operand {op}.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 void MarkAsRepresentation(MachineRepresentation rep,
212 const InstructionOperand& op);
213
214 enum CallBufferFlag {
215 kCallCodeImmediate = 1u << 0,
216 kCallAddressImmediate = 1u << 1,
217 kCallTail = 1u << 2
218 };
219 typedef base::Flags<CallBufferFlag> CallBufferFlags;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221 // Initialize the call buffer with the InstructionOperands, nodes, etc,
222 // corresponding
223 // to the inputs and outputs of the call.
224 // {call_code_immediate} to generate immediate operands to calls of code.
225 // {call_address_immediate} to generate immediate operands to address calls.
226 void InitializeCallBuffer(Node* call, CallBuffer* buffer,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 CallBufferFlags flags, int stack_param_delta = 0);
228 bool IsTailCallAddressImmediate();
Ben Murdochda12d292016-06-02 14:46:10 +0100229 int GetTempsCountForTailCallFromJSFunction();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000230
231 FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232
233 // ===========================================================================
234 // ============= Architecture-specific graph covering methods. ===============
235 // ===========================================================================
236
237 // Visit nodes in the given block and generate code.
238 void VisitBlock(BasicBlock* block);
239
240 // Visit the node for the control flow at the end of the block, generating
241 // code if necessary.
242 void VisitControl(BasicBlock* block);
243
244 // Visit the node and generate code, if any.
245 void VisitNode(Node* node);
246
Ben Murdoch61f157c2016-09-16 13:49:30 +0100247 // Visit the node and generate code for IEEE 754 functions.
248 void VisitFloat64Ieee754Binop(Node*, InstructionCode code);
249 void VisitFloat64Ieee754Unop(Node*, InstructionCode code);
250
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000251#define DECLARE_GENERATOR(x) void Visit##x(Node* node);
252 MACHINE_OP_LIST(DECLARE_GENERATOR)
253#undef DECLARE_GENERATOR
254
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 void VisitFinishRegion(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 void VisitParameter(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000257 void VisitIfException(Node* node);
258 void VisitOsrValue(Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000259 void VisitPhi(Node* node);
260 void VisitProjection(Node* node);
261 void VisitConstant(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262 void VisitCall(Node* call, BasicBlock* handler = nullptr);
Ben Murdochda12d292016-06-02 14:46:10 +0100263 void VisitDeoptimizeIf(Node* node);
264 void VisitDeoptimizeUnless(Node* node);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 void VisitTailCall(Node* call);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000266 void VisitGoto(BasicBlock* target);
267 void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 void VisitSwitch(Node* node, const SwitchInfo& sw);
269 void VisitDeoptimize(DeoptimizeKind kind, Node* value);
270 void VisitReturn(Node* ret);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 void VisitThrow(Node* value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272
273 void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
274 const CallDescriptor* descriptor, Node* node);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275
Ben Murdoch61f157c2016-09-16 13:49:30 +0100276 void EmitIdentity(Node* node);
277 bool CanProduceSignalingNaN(Node* node);
278
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000279 // ===========================================================================
280
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400281 Schedule* schedule() const { return schedule_; }
282 Linkage* linkage() const { return linkage_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000283 InstructionSequence* sequence() const { return sequence_; }
284 Zone* instruction_zone() const { return sequence()->zone(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400285 Zone* zone() const { return zone_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286
287 // ===========================================================================
288
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400289 Zone* const zone_;
290 Linkage* const linkage_;
291 InstructionSequence* const sequence_;
292 SourcePositionTable* const source_positions_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 SourcePositionMode const source_position_mode_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 Features features_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400295 Schedule* const schedule_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 BasicBlock* current_block_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 ZoneVector<Instruction*> instructions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 BoolVector defined_;
299 BoolVector used_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 IntVector effect_level_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 IntVector virtual_registers_;
302 InstructionScheduler* scheduler_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100303 Frame* frame_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000304};
305
306} // namespace compiler
307} // namespace internal
308} // namespace v8
309
310#endif // V8_COMPILER_INSTRUCTION_SELECTOR_H_