Home | History | Annotate | Download | only in compiler
      1 // 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 
      8 #include <map>
      9 
     10 #include "src/compiler/common-operator.h"
     11 #include "src/compiler/instruction-scheduler.h"
     12 #include "src/compiler/instruction.h"
     13 #include "src/compiler/machine-operator.h"
     14 #include "src/compiler/node.h"
     15 #include "src/globals.h"
     16 #include "src/zone/zone-containers.h"
     17 
     18 namespace v8 {
     19 namespace internal {
     20 namespace compiler {
     21 
     22 // Forward declarations.
     23 class BasicBlock;
     24 struct CallBuffer;  // TODO(bmeurer): Remove this.
     25 class FlagsContinuation;
     26 class Linkage;
     27 class OperandGenerator;
     28 struct SwitchInfo;
     29 
     30 // This struct connects nodes of parameters which are going to be pushed on the
     31 // call stack with their parameter index in the call descriptor of the callee.
     32 class PushParameter {
     33  public:
     34   PushParameter() : node_(nullptr), type_(MachineType::None()) {}
     35   PushParameter(Node* node, MachineType type) : node_(node), type_(type) {}
     36 
     37   Node* node() const { return node_; }
     38   MachineType type() const { return type_; }
     39 
     40  private:
     41   Node* node_;
     42   MachineType type_;
     43 };
     44 
     45 // Instruction selection generates an InstructionSequence for a given Schedule.
     46 class V8_EXPORT_PRIVATE InstructionSelector final {
     47  public:
     48   // Forward declarations.
     49   class Features;
     50 
     51   enum SourcePositionMode { kCallSourcePositions, kAllSourcePositions };
     52   enum EnableScheduling { kDisableScheduling, kEnableScheduling };
     53   enum EnableSerialization { kDisableSerialization, kEnableSerialization };
     54 
     55   InstructionSelector(
     56       Zone* zone, size_t node_count, Linkage* linkage,
     57       InstructionSequence* sequence, Schedule* schedule,
     58       SourcePositionTable* source_positions, Frame* frame,
     59       SourcePositionMode source_position_mode = kCallSourcePositions,
     60       Features features = SupportedFeatures(),
     61       EnableScheduling enable_scheduling = FLAG_turbo_instruction_scheduling
     62                                                ? kEnableScheduling
     63                                                : kDisableScheduling,
     64       EnableSerialization enable_serialization = kDisableSerialization);
     65 
     66   // Visit code for the entire graph with the included schedule.
     67   bool SelectInstructions();
     68 
     69   void StartBlock(RpoNumber rpo);
     70   void EndBlock(RpoNumber rpo);
     71   void AddInstruction(Instruction* instr);
     72 
     73   // ===========================================================================
     74   // ============= Architecture-independent code emission methods. =============
     75   // ===========================================================================
     76 
     77   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     78                     size_t temp_count = 0, InstructionOperand* temps = nullptr);
     79   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     80                     InstructionOperand a, size_t temp_count = 0,
     81                     InstructionOperand* temps = nullptr);
     82   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     83                     InstructionOperand a, InstructionOperand b,
     84                     size_t temp_count = 0, InstructionOperand* temps = nullptr);
     85   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     86                     InstructionOperand a, InstructionOperand b,
     87                     InstructionOperand c, size_t temp_count = 0,
     88                     InstructionOperand* temps = nullptr);
     89   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     90                     InstructionOperand a, InstructionOperand b,
     91                     InstructionOperand c, InstructionOperand d,
     92                     size_t temp_count = 0, InstructionOperand* temps = nullptr);
     93   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     94                     InstructionOperand a, InstructionOperand b,
     95                     InstructionOperand c, InstructionOperand d,
     96                     InstructionOperand e, size_t temp_count = 0,
     97                     InstructionOperand* temps = nullptr);
     98   Instruction* Emit(InstructionCode opcode, InstructionOperand output,
     99                     InstructionOperand a, InstructionOperand b,
    100                     InstructionOperand c, InstructionOperand d,
    101                     InstructionOperand e, InstructionOperand f,
    102                     size_t temp_count = 0, InstructionOperand* temps = nullptr);
    103   Instruction* Emit(InstructionCode opcode, size_t output_count,
    104                     InstructionOperand* outputs, size_t input_count,
    105                     InstructionOperand* inputs, size_t temp_count = 0,
    106                     InstructionOperand* temps = nullptr);
    107   Instruction* Emit(Instruction* instr);
    108 
    109   // ===========================================================================
    110   // ===== Architecture-independent deoptimization exit emission methods. ======
    111   // ===========================================================================
    112 
    113   Instruction* EmitDeoptimize(InstructionCode opcode, InstructionOperand output,
    114                               InstructionOperand a, DeoptimizeReason reason,
    115                               Node* frame_state);
    116   Instruction* EmitDeoptimize(InstructionCode opcode, InstructionOperand output,
    117                               InstructionOperand a, InstructionOperand b,
    118                               DeoptimizeReason reason, Node* frame_state);
    119   Instruction* EmitDeoptimize(InstructionCode opcode, size_t output_count,
    120                               InstructionOperand* outputs, size_t input_count,
    121                               InstructionOperand* inputs,
    122                               DeoptimizeReason reason, Node* frame_state);
    123 
    124   // ===========================================================================
    125   // ============== Architecture-independent CPU feature methods. ==============
    126   // ===========================================================================
    127 
    128   class Features final {
    129    public:
    130     Features() : bits_(0) {}
    131     explicit Features(unsigned bits) : bits_(bits) {}
    132     explicit Features(CpuFeature f) : bits_(1u << f) {}
    133     Features(CpuFeature f1, CpuFeature f2) : bits_((1u << f1) | (1u << f2)) {}
    134 
    135     bool Contains(CpuFeature f) const { return (bits_ & (1u << f)); }
    136 
    137    private:
    138     unsigned bits_;
    139   };
    140 
    141   bool IsSupported(CpuFeature feature) const {
    142     return features_.Contains(feature);
    143   }
    144 
    145   // Returns the features supported on the target platform.
    146   static Features SupportedFeatures() {
    147     return Features(CpuFeatures::SupportedFeatures());
    148   }
    149 
    150   // TODO(sigurds) This should take a CpuFeatures argument.
    151   static MachineOperatorBuilder::Flags SupportedMachineOperatorFlags();
    152 
    153   static MachineOperatorBuilder::AlignmentRequirements AlignmentRequirements();
    154 
    155   // ===========================================================================
    156   // ============ Architecture-independent graph covering methods. =============
    157   // ===========================================================================
    158 
    159   // Used in pattern matching during code generation.
    160   // Check if {node} can be covered while generating code for the current
    161   // instruction. A node can be covered if the {user} of the node has the only
    162   // edge and the two are in the same basic block.
    163   bool CanCover(Node* user, Node* node) const;
    164 
    165   // Used in pattern matching during code generation.
    166   // This function checks that {node} and {user} are in the same basic block,
    167   // and that {user} is the only user of {node} in this basic block.  This
    168   // check guarantees that there are no users of {node} scheduled between
    169   // {node} and {user}, and thus we can select a single instruction for both
    170   // nodes, if such an instruction exists. This check can be used for example
    171   // when selecting instructions for:
    172   //   n = Int32Add(a, b)
    173   //   c = Word32Compare(n, 0, cond)
    174   //   Branch(c, true_label, false_label)
    175   // Here we can generate a flag-setting add instruction, even if the add has
    176   // uses in other basic blocks, since the flag-setting add instruction will
    177   // still generate the result of the addition and not just set the flags.
    178   // However, if we had uses of the add in the same basic block, we could have:
    179   //   n = Int32Add(a, b)
    180   //   o = OtherOp(n, ...)
    181   //   c = Word32Compare(n, 0, cond)
    182   //   Branch(c, true_label, false_label)
    183   // where we cannot select the add and the compare together.  If we were to
    184   // select a flag-setting add instruction for Word32Compare and Int32Add while
    185   // visiting Word32Compare, we would then have to select an instruction for
    186   // OtherOp *afterwards*, which means we would attempt to use the result of
    187   // the add before we have defined it.
    188   bool IsOnlyUserOfNodeInSameBlock(Node* user, Node* node) const;
    189 
    190   // Checks if {node} was already defined, and therefore code was already
    191   // generated for it.
    192   bool IsDefined(Node* node) const;
    193 
    194   // Checks if {node} has any uses, and therefore code has to be generated for
    195   // it.
    196   bool IsUsed(Node* node) const;
    197 
    198   // Checks if {node} is currently live.
    199   bool IsLive(Node* node) const { return !IsDefined(node) && IsUsed(node); }
    200 
    201   // Gets the effect level of {node}.
    202   int GetEffectLevel(Node* node) const;
    203 
    204   int GetVirtualRegister(const Node* node);
    205   const std::map<NodeId, int> GetVirtualRegistersForTesting() const;
    206 
    207   // Check if we can generate loads and stores of ExternalConstants relative
    208   // to the roots register, i.e. if both a root register is available for this
    209   // compilation unit and the serializer is disabled.
    210   bool CanAddressRelativeToRootsRegister() const;
    211   // Check if we can use the roots register to access GC roots.
    212   bool CanUseRootsRegister() const;
    213 
    214   Isolate* isolate() const { return sequence()->isolate(); }
    215 
    216  private:
    217   friend class OperandGenerator;
    218 
    219   bool UseInstructionScheduling() const {
    220     return (enable_scheduling_ == kEnableScheduling) &&
    221            InstructionScheduler::SchedulerSupported();
    222   }
    223 
    224   void EmitTableSwitch(const SwitchInfo& sw, InstructionOperand& index_operand);
    225   void EmitLookupSwitch(const SwitchInfo& sw,
    226                         InstructionOperand& value_operand);
    227 
    228   void TryRename(InstructionOperand* op);
    229   int GetRename(int virtual_register);
    230   void SetRename(const Node* node, const Node* rename);
    231   void UpdateRenames(Instruction* instruction);
    232   void UpdateRenamesInPhi(PhiInstruction* phi);
    233 
    234   // Inform the instruction selection that {node} was just defined.
    235   void MarkAsDefined(Node* node);
    236 
    237   // Inform the instruction selection that {node} has at least one use and we
    238   // will need to generate code for it.
    239   void MarkAsUsed(Node* node);
    240 
    241   // Sets the effect level of {node}.
    242   void SetEffectLevel(Node* node, int effect_level);
    243 
    244   // Inform the register allocation of the representation of the value produced
    245   // by {node}.
    246   void MarkAsRepresentation(MachineRepresentation rep, Node* node);
    247   void MarkAsWord32(Node* node) {
    248     MarkAsRepresentation(MachineRepresentation::kWord32, node);
    249   }
    250   void MarkAsWord64(Node* node) {
    251     MarkAsRepresentation(MachineRepresentation::kWord64, node);
    252   }
    253   void MarkAsFloat32(Node* node) {
    254     MarkAsRepresentation(MachineRepresentation::kFloat32, node);
    255   }
    256   void MarkAsFloat64(Node* node) {
    257     MarkAsRepresentation(MachineRepresentation::kFloat64, node);
    258   }
    259   void MarkAsSimd128(Node* node) {
    260     MarkAsRepresentation(MachineRepresentation::kSimd128, node);
    261   }
    262   void MarkAsReference(Node* node) {
    263     MarkAsRepresentation(MachineRepresentation::kTagged, node);
    264   }
    265 
    266   // Inform the register allocation of the representation of the unallocated
    267   // operand {op}.
    268   void MarkAsRepresentation(MachineRepresentation rep,
    269                             const InstructionOperand& op);
    270 
    271   enum CallBufferFlag {
    272     kCallCodeImmediate = 1u << 0,
    273     kCallAddressImmediate = 1u << 1,
    274     kCallTail = 1u << 2
    275   };
    276   typedef base::Flags<CallBufferFlag> CallBufferFlags;
    277 
    278   // Initialize the call buffer with the InstructionOperands, nodes, etc,
    279   // corresponding
    280   // to the inputs and outputs of the call.
    281   // {call_code_immediate} to generate immediate operands to calls of code.
    282   // {call_address_immediate} to generate immediate operands to address calls.
    283   void InitializeCallBuffer(Node* call, CallBuffer* buffer,
    284                             CallBufferFlags flags, int stack_slot_delta = 0);
    285   bool IsTailCallAddressImmediate();
    286   int GetTempsCountForTailCallFromJSFunction();
    287 
    288   FrameStateDescriptor* GetFrameStateDescriptor(Node* node);
    289 
    290   // ===========================================================================
    291   // ============= Architecture-specific graph covering methods. ===============
    292   // ===========================================================================
    293 
    294   // Visit nodes in the given block and generate code.
    295   void VisitBlock(BasicBlock* block);
    296 
    297   // Visit the node for the control flow at the end of the block, generating
    298   // code if necessary.
    299   void VisitControl(BasicBlock* block);
    300 
    301   // Visit the node and generate code, if any.
    302   void VisitNode(Node* node);
    303 
    304   // Visit the node and generate code for IEEE 754 functions.
    305   void VisitFloat64Ieee754Binop(Node*, InstructionCode code);
    306   void VisitFloat64Ieee754Unop(Node*, InstructionCode code);
    307 
    308 #define DECLARE_GENERATOR(x) void Visit##x(Node* node);
    309   MACHINE_OP_LIST(DECLARE_GENERATOR)
    310   MACHINE_SIMD_RETURN_NUM_OP_LIST(DECLARE_GENERATOR)
    311   MACHINE_SIMD_RETURN_SIMD_OP_LIST(DECLARE_GENERATOR)
    312 #undef DECLARE_GENERATOR
    313 
    314   void VisitFinishRegion(Node* node);
    315   void VisitParameter(Node* node);
    316   void VisitIfException(Node* node);
    317   void VisitOsrValue(Node* node);
    318   void VisitPhi(Node* node);
    319   void VisitProjection(Node* node);
    320   void VisitConstant(Node* node);
    321   void VisitCall(Node* call, BasicBlock* handler = nullptr);
    322   void VisitDeoptimizeIf(Node* node);
    323   void VisitDeoptimizeUnless(Node* node);
    324   void VisitTailCall(Node* call);
    325   void VisitGoto(BasicBlock* target);
    326   void VisitBranch(Node* input, BasicBlock* tbranch, BasicBlock* fbranch);
    327   void VisitSwitch(Node* node, const SwitchInfo& sw);
    328   void VisitDeoptimize(DeoptimizeKind kind, DeoptimizeReason reason,
    329                        Node* value);
    330   void VisitReturn(Node* ret);
    331   void VisitThrow(Node* value);
    332   void VisitRetain(Node* node);
    333 
    334   void EmitPrepareArguments(ZoneVector<compiler::PushParameter>* arguments,
    335                             const CallDescriptor* descriptor, Node* node);
    336 
    337   void EmitIdentity(Node* node);
    338   bool CanProduceSignalingNaN(Node* node);
    339 
    340   // ===========================================================================
    341 
    342   Schedule* schedule() const { return schedule_; }
    343   Linkage* linkage() const { return linkage_; }
    344   InstructionSequence* sequence() const { return sequence_; }
    345   Zone* instruction_zone() const { return sequence()->zone(); }
    346   Zone* zone() const { return zone_; }
    347 
    348   void set_instruction_selection_failed() {
    349     instruction_selection_failed_ = true;
    350   }
    351   bool instruction_selection_failed() { return instruction_selection_failed_; }
    352 
    353   void MarkPairProjectionsAsWord32(Node* node);
    354 
    355   // ===========================================================================
    356 
    357   Zone* const zone_;
    358   Linkage* const linkage_;
    359   InstructionSequence* const sequence_;
    360   SourcePositionTable* const source_positions_;
    361   SourcePositionMode const source_position_mode_;
    362   Features features_;
    363   Schedule* const schedule_;
    364   BasicBlock* current_block_;
    365   ZoneVector<Instruction*> instructions_;
    366   BoolVector defined_;
    367   BoolVector used_;
    368   IntVector effect_level_;
    369   IntVector virtual_registers_;
    370   IntVector virtual_register_rename_;
    371   InstructionScheduler* scheduler_;
    372   EnableScheduling enable_scheduling_;
    373   EnableSerialization enable_serialization_;
    374   Frame* frame_;
    375   bool instruction_selection_failed_;
    376 };
    377 
    378 }  // namespace compiler
    379 }  // namespace internal
    380 }  // namespace v8
    381 
    382 #endif  // V8_COMPILER_INSTRUCTION_SELECTOR_H_
    383