Path: blob/master/src/hotspot/share/c1/c1_LinearScan.hpp
40931 views
/*1* Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_C1_C1_LINEARSCAN_HPP25#define SHARE_C1_C1_LINEARSCAN_HPP2627#include "c1/c1_FpuStackSim.hpp"28#include "c1/c1_FrameMap.hpp"29#include "c1/c1_IR.hpp"30#include "c1/c1_Instruction.hpp"31#include "c1/c1_LIR.hpp"32#include "c1/c1_LIRGenerator.hpp"33#include "compiler/oopMap.hpp"34#include "utilities/align.hpp"35#include "utilities/macros.hpp"3637class FpuStackAllocator;38class IRScopeDebugInfo;39class Interval;40class IntervalWalker;41class LIRGenerator;42class LinearScan;43class MoveResolver;44class Range;4546typedef GrowableArray<Interval*> IntervalArray;47typedef GrowableArray<Interval*> IntervalList;48typedef GrowableArray<IntervalList*> IntervalsList;49typedef GrowableArray<ScopeValue*> ScopeValueArray;50typedef GrowableArray<LIR_OpList*> LIR_OpListStack;5152enum IntervalUseKind {53// priority of use kinds must be ascending54noUse = 0,55loopEndMarker = 1,56shouldHaveRegister = 2,57mustHaveRegister = 3,5859firstValidKind = 1,60lastValidKind = 361};6263enum IntervalKind {64fixedKind = 0, // interval pre-colored by LIR_Generator65anyKind = 1, // no register/memory allocated by LIR_Generator66nofKinds,67firstKind = fixedKind68};697071// during linear scan an interval is in one of four states in72enum IntervalState {73unhandledState = 0, // unhandled state (not processed yet)74activeState = 1, // life and is in a physical register75inactiveState = 2, // in a life time hole and is in a physical register76handledState = 3, // spilled or not life again77invalidState = -178};798081enum IntervalSpillState {82noDefinitionFound, // starting state of calculation: no definition found yet83oneDefinitionFound, // one definition has already been found.84// Note: two consecutive definitions are treated as one (e.g. consecutive move and add because of two-operand LIR form)85// the position of this definition is stored in _definition_pos86oneMoveInserted, // one spill move has already been inserted.87storeAtDefinition, // the interval should be stored immediately after its definition because otherwise88// there would be multiple redundant stores89startInMemory, // the interval starts in memory (e.g. method parameter), so a store is never necessary90noOptimization // the interval has more then one definition (e.g. resulting from phi moves), so stores to memory are not optimized91};929394#define for_each_interval_kind(kind) \95for (IntervalKind kind = firstKind; kind < nofKinds; kind = (IntervalKind)(kind + 1))9697#define for_each_visitor_mode(mode) \98for (LIR_OpVisitState::OprMode mode = LIR_OpVisitState::firstMode; mode < LIR_OpVisitState::numModes; mode = (LIR_OpVisitState::OprMode)(mode + 1))99100101class LinearScan : public CompilationResourceObj {102// declare classes used by LinearScan as friends because they103// need a wide variety of functions declared here104//105// Only the small interface to the rest of the compiler is public106friend class Interval;107friend class IntervalWalker;108friend class LinearScanWalker;109friend class FpuStackAllocator;110friend class MoveResolver;111friend class LinearScanStatistic;112friend class LinearScanTimers;113friend class RegisterVerifier;114115public:116enum {117any_reg = -1,118nof_cpu_regs = pd_nof_cpu_regs_linearscan,119nof_fpu_regs = pd_nof_fpu_regs_linearscan,120nof_xmm_regs = pd_nof_xmm_regs_linearscan,121nof_regs = nof_cpu_regs + nof_fpu_regs + nof_xmm_regs122};123124private:125Compilation* _compilation;126IR* _ir;127LIRGenerator* _gen;128FrameMap* _frame_map;129130BlockList _cached_blocks; // cached list with all blocks in linear-scan order (only correct if original list keeps unchanged)131int _num_virtual_regs; // number of virtual registers (without new registers introduced because of splitting intervals)132bool _has_fpu_registers; // true if this method uses any floating point registers (and so fpu stack allocation is necessary)133int _num_calls; // total number of calls in this method134int _max_spills; // number of stack slots used for intervals allocated to memory135int _unused_spill_slot; // unused spill slot for a single-word value because of alignment of a double-word value136137IntervalList _intervals; // mapping from register number to interval138IntervalList* _new_intervals_from_allocation; // list with all intervals created during allocation when an existing interval is split139IntervalArray* _sorted_intervals; // intervals sorted by Interval::from()140bool _needs_full_resort; // set to true if an Interval::from() is changed and _sorted_intervals must be resorted141142LIR_OpArray _lir_ops; // mapping from LIR_Op id to LIR_Op node143BlockBeginArray _block_of_op; // mapping from LIR_Op id to the BlockBegin containing this instruction144ResourceBitMap _has_info; // bit set for each LIR_Op id that has a CodeEmitInfo145ResourceBitMap _has_call; // bit set for each LIR_Op id that destroys all caller save registers146BitMap2D _interval_in_loop; // bit set for each virtual register that is contained in each loop147148// cached debug info to prevent multiple creation of same object149// TODO: cached scope values for registers could be static150ScopeValueArray _scope_value_cache;151152static ConstantOopWriteValue* _oop_null_scope_value;153static ConstantIntValue* _int_m1_scope_value;154static ConstantIntValue* _int_0_scope_value;155static ConstantIntValue* _int_1_scope_value;156static ConstantIntValue* _int_2_scope_value;157158// accessors159IR* ir() const { return _ir; }160Compilation* compilation() const { return _compilation; }161LIRGenerator* gen() const { return _gen; }162FrameMap* frame_map() const { return _frame_map; }163164// unified bailout support165void bailout(const char* msg) const { compilation()->bailout(msg); }166bool bailed_out() const { return compilation()->bailed_out(); }167168// access to block list (sorted in linear scan order)169int block_count() const { assert(_cached_blocks.length() == ir()->linear_scan_order()->length(), "invalid cached block list"); return _cached_blocks.length(); }170BlockBegin* block_at(int idx) const { assert(_cached_blocks.at(idx) == ir()->linear_scan_order()->at(idx), "invalid cached block list"); return _cached_blocks.at(idx); }171172int num_virtual_regs() const { return _num_virtual_regs; }173// size of live_in and live_out sets of BasicBlocks (BitMap needs rounded size for iteration)174int live_set_size() const { return align_up(_num_virtual_regs, BitsPerWord); }175bool has_fpu_registers() const { return _has_fpu_registers; }176int num_loops() const { return ir()->num_loops(); }177bool is_interval_in_loop(int interval, int loop) const { return _interval_in_loop.at(interval, loop); }178179// handling of fpu stack allocation (platform dependent, needed for debug information generation)180#ifdef IA32181FpuStackAllocator* _fpu_stack_allocator;182bool use_fpu_stack_allocation() const { return UseSSE < 2 && has_fpu_registers(); }183#else184bool use_fpu_stack_allocation() const { return false; }185#endif186187188// access to interval list189int interval_count() const { return _intervals.length(); }190Interval* interval_at(int reg_num) const { return _intervals.at(reg_num); }191192// access to LIR_Ops and Blocks indexed by op_id193int max_lir_op_id() const { assert(_lir_ops.length() > 0, "no operations"); return (_lir_ops.length() - 1) << 1; }194LIR_Op* lir_op_with_id(int op_id) const { assert(op_id >= 0 && op_id <= max_lir_op_id() && op_id % 2 == 0, "op_id out of range or not even"); return _lir_ops.at(op_id >> 1); }195BlockBegin* block_of_op_with_id(int op_id) const { assert(_block_of_op.length() > 0 && op_id >= 0 && op_id <= max_lir_op_id() + 1, "op_id out of range"); return _block_of_op.at(op_id >> 1); }196197bool is_block_begin(int op_id) { return op_id == 0 || block_of_op_with_id(op_id) != block_of_op_with_id(op_id - 1); }198199bool has_call(int op_id) { assert(op_id % 2 == 0, "must be even"); return _has_call.at(op_id >> 1); }200bool has_info(int op_id) { assert(op_id % 2 == 0, "must be even"); return _has_info.at(op_id >> 1); }201202203// functions for converting LIR-Operands to register numbers204static bool is_valid_reg_num(int reg_num) { return reg_num >= 0; }205static int reg_num(LIR_Opr opr);206static int reg_numHi(LIR_Opr opr);207208// functions for classification of intervals209static bool is_precolored_interval(const Interval* i);210static bool is_virtual_interval(const Interval* i);211212static bool is_precolored_cpu_interval(const Interval* i);213static bool is_virtual_cpu_interval(const Interval* i);214static bool is_precolored_fpu_interval(const Interval* i);215static bool is_virtual_fpu_interval(const Interval* i);216217static bool is_in_fpu_register(const Interval* i);218static bool is_oop_interval(const Interval* i);219220221// General helper functions222int allocate_spill_slot(bool double_word);223void assign_spill_slot(Interval* it);224void propagate_spill_slots();225226Interval* create_interval(int reg_num);227void append_interval(Interval* it);228void copy_register_flags(Interval* from, Interval* to);229230// platform dependent functions231static bool is_processed_reg_num(int reg_num);232static int num_physical_regs(BasicType type);233static bool requires_adjacent_regs(BasicType type);234static bool is_caller_save(int assigned_reg);235236// spill move optimization: eliminate moves from register to stack if237// stack slot is known to be correct238void change_spill_definition_pos(Interval* interval, int def_pos);239void change_spill_state(Interval* interval, int spill_pos);240static bool must_store_at_definition(const Interval* i);241void eliminate_spill_moves();242243// Phase 1: number all instructions in all blocks244void number_instructions();245246// Phase 2: compute local live sets separately for each block247// (sets live_gen and live_kill for each block)248//249// helper methods used by compute_local_live_sets()250void set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill);251252void compute_local_live_sets();253254// Phase 3: perform a backward dataflow analysis to compute global live sets255// (sets live_in and live_out for each block)256void compute_global_live_sets();257258259// Phase 4: build intervals260// (fills the list _intervals)261//262// helper methods used by build_intervals()263void add_use (Value value, int from, int to, IntervalUseKind use_kind);264265void add_def (LIR_Opr opr, int def_pos, IntervalUseKind use_kind);266void add_use (LIR_Opr opr, int from, int to, IntervalUseKind use_kind);267void add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind);268269void add_def (int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type);270void add_use (int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type);271void add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type);272273// Add platform dependent kills for particular LIR ops. Can be used274// to add platform dependent behaviour for some operations.275void pd_add_temps(LIR_Op* op);276277IntervalUseKind use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr);278IntervalUseKind use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr);279void handle_method_arguments(LIR_Op* op);280void handle_doubleword_moves(LIR_Op* op);281void add_register_hints(LIR_Op* op);282283void build_intervals();284285286// Phase 5: actual register allocation287// (Uses LinearScanWalker)288//289// helper functions for building a sorted list of intervals290NOT_PRODUCT(bool is_sorted(IntervalArray* intervals);)291static int interval_cmp(Interval** a, Interval** b);292void add_to_list(Interval** first, Interval** prev, Interval* interval);293void create_unhandled_lists(Interval** list1, Interval** list2, bool (is_list1)(const Interval* i), bool (is_list2)(const Interval* i));294295void sort_intervals_before_allocation();296void sort_intervals_after_allocation();297void allocate_registers();298299300// Phase 6: resolve data flow301// (insert moves at edges between blocks if intervals have been split)302//303// helper functions for resolve_data_flow()304Interval* split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode);305Interval* interval_at_block_begin(BlockBegin* block, int reg_num);306Interval* interval_at_block_end(BlockBegin* block, int reg_num);307Interval* interval_at_op_id(int reg_num, int op_id);308void resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);309void resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver);310void resolve_data_flow();311312void resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver);313void resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver);314void resolve_exception_edge(XHandler* handler, int throwing_op_id, int reg_num, Phi* phi, MoveResolver &move_resolver);315void resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver);316void resolve_exception_handlers();317318// Phase 7: assign register numbers back to LIR319// (includes computation of debug information and oop maps)320//321// helper functions for assign_reg_num()322VMReg vm_reg_for_interval(Interval* interval);323VMReg vm_reg_for_operand(LIR_Opr opr);324325static LIR_Opr operand_for_interval(Interval* interval);326static LIR_Opr calc_operand_for_interval(const Interval* interval);327LIR_Opr canonical_spill_opr(Interval* interval);328329LIR_Opr color_lir_opr(LIR_Opr opr, int id, LIR_OpVisitState::OprMode);330331// methods used for oop map computation332IntervalWalker* init_compute_oop_maps();333OopMap* compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site);334void compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op);335336// methods used for debug information computation337void init_compute_debug_info();338339MonitorValue* location_for_monitor_index(int monitor_index);340LocationValue* location_for_name(int name, Location::Type loc_type);341void set_oop(OopMap* map, VMReg name) {342if (map->legal_vm_reg_name(name)) {343map->set_oop(name);344} else {345bailout("illegal oopMap register name");346}347}348349int append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);350int append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values);351int append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values);352353IRScopeDebugInfo* compute_debug_info_for_scope(int op_id, IRScope* cur_scope, ValueStack* cur_state, ValueStack* innermost_state);354void compute_debug_info(CodeEmitInfo* info, int op_id);355356void assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw);357void assign_reg_num();358359360// Phase 8: fpu stack allocation361// (Used only on x86 when fpu operands are present)362void allocate_fpu_stack();363364365// helper functions for printing state366#ifndef PRODUCT367static void print_bitmap(BitMap& bitmap);368void print_intervals(const char* label);369void print_lir(int level, const char* label, bool hir_valid = true);370static void print_reg_num(int reg_num) { print_reg_num(tty, reg_num); }371static void print_reg_num(outputStream* out, int reg_num);372static LIR_Opr get_operand(int reg_num);373#endif374375#ifdef ASSERT376// verification functions for allocation377// (check that all intervals have a correct register and that no registers are overwritten)378void verify();379void verify_intervals();380void verify_no_oops_in_fixed_intervals();381void verify_constants();382void verify_registers();383#endif384385public:386// creation387LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map);388389// main entry function: perform linear scan register allocation390void do_linear_scan();391392// accessors used by Compilation393int max_spills() const { return _max_spills; }394int num_calls() const { assert(_num_calls >= 0, "not set"); return _num_calls; }395396#ifndef PRODUCT397// entry functions for printing398static void print_statistics();399static void print_timers(double total);400401// Used for debugging402Interval* find_interval_at(int reg_num) const;403#endif404};405406407// Helper class for ordering moves that are inserted at the same position in the LIR408// When moves between registers are inserted, it is important that the moves are409// ordered such that no register is overwritten. So moves from register to stack410// are processed prior to moves from stack to register. When moves have circular411// dependencies, a temporary stack slot is used to break the circle.412// The same logic is used in the LinearScanWalker and in LinearScan during resolve_data_flow413// and therefore factored out in a separate class414class MoveResolver: public StackObj {415private:416LinearScan* _allocator;417418LIR_List* _insert_list;419int _insert_idx;420LIR_InsertionBuffer _insertion_buffer; // buffer where moves are inserted421422IntervalList _mapping_from;423LIR_OprList _mapping_from_opr;424IntervalList _mapping_to;425bool _multiple_reads_allowed;426int _register_blocked[LinearScan::nof_regs];427428int register_blocked(int reg) { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); return _register_blocked[reg]; }429void set_register_blocked(int reg, int direction) { assert(reg >= 0 && reg < LinearScan::nof_regs, "out of bounds"); assert(direction == 1 || direction == -1, "out of bounds"); _register_blocked[reg] += direction; }430431void block_registers(Interval* it);432void unblock_registers(Interval* it);433bool save_to_process_move(Interval* from, Interval* to);434435void create_insertion_buffer(LIR_List* list);436void append_insertion_buffer();437void insert_move(Interval* from_interval, Interval* to_interval);438void insert_move(LIR_Opr from_opr, Interval* to_interval);439LIR_Opr get_virtual_register(Interval* interval);440441DEBUG_ONLY(void verify_before_resolve();)442void resolve_mappings();443public:444MoveResolver(LinearScan* allocator);445446DEBUG_ONLY(void check_empty();)447void set_multiple_reads_allowed() { _multiple_reads_allowed = true; }448void set_insert_position(LIR_List* insert_list, int insert_idx);449void move_insert_position(LIR_List* insert_list, int insert_idx);450void add_mapping(Interval* from, Interval* to);451void add_mapping(LIR_Opr from, Interval* to);452void resolve_and_append_moves();453454LinearScan* allocator() { return _allocator; }455bool has_mappings() { return _mapping_from.length() > 0; }456};457458459class Range : public CompilationResourceObj {460friend class Interval;461462private:463static Range* _end; // sentinel (from == to == max_jint)464465int _from; // from (inclusive)466int _to; // to (exclusive)467Range* _next; // linear list of Ranges468469// used only by class Interval, so hide them470bool intersects(Range* r) const { return intersects_at(r) != -1; }471int intersects_at(Range* r) const;472473public:474Range(int from, int to, Range* next);475476static void initialize(Arena* arena);477static Range* end() { return _end; }478479int from() const { return _from; }480int to() const { return _to; }481Range* next() const { return _next; }482void set_from(int from) { _from = from; }483void set_to(int to) { _to = to; }484void set_next(Range* next) { _next = next; }485486// for testing487void print(outputStream* out = tty) const PRODUCT_RETURN;488};489490491// Interval is an ordered list of disjoint ranges.492493// For pre-colored double word LIR_Oprs, one interval is created for494// the low word register and one is created for the hi word register.495// On Intel for FPU double registers only one interval is created. At496// all times assigned_reg contains the reg. number of the physical497// register.498499// For LIR_Opr in virtual registers a single interval can represent500// single and double word values. When a physical register is501// assigned to the interval, assigned_reg contains the502// phys. reg. number and for double word values assigned_regHi the503// phys. reg. number of the hi word if there is any. For spilled504// intervals assigned_reg contains the stack index. assigned_regHi is505// always -1.506507class Interval : public CompilationResourceObj {508private:509static Interval* _end; // sentinel (interval with only range Range::end())510511int _reg_num;512BasicType _type; // valid only for virtual registers513Range* _first; // sorted list of Ranges514intStack _use_pos_and_kinds; // sorted list of use-positions and their according use-kinds515516Range* _current; // interval iteration: the current Range517Interval* _next; // interval iteration: sorted list of Intervals (ends with sentinel)518IntervalState _state; // interval iteration: to which set belongs this interval519520521int _assigned_reg;522int _assigned_regHi;523524int _cached_to; // cached value: to of last range (-1: not cached)525LIR_Opr _cached_opr;526VMReg _cached_vm_reg;527528Interval* _split_parent; // the original interval where this interval is derived from529IntervalList* _split_children; // list of all intervals that are split off from this interval (only available for split parents)530Interval* _current_split_child; // the current split child that has been active or inactive last (always stored in split parents)531532int _canonical_spill_slot; // the stack slot where all split parts of this interval are spilled to (always stored in split parents)533bool _insert_move_when_activated; // true if move is inserted between _current_split_child and this interval when interval gets active the first time534IntervalSpillState _spill_state; // for spill move optimization535int _spill_definition_pos; // position where the interval is defined (if defined only once)536Interval* _register_hint; // this interval should be in the same register as the hint interval537538int calc_to();539Interval* new_split_child();540public:541Interval(int reg_num);542543static void initialize(Arena* arena);544static Interval* end() { return _end; }545546// accessors547int reg_num() const { return _reg_num; }548void set_reg_num(int r) { assert(_reg_num == -1, "cannot change reg_num"); _reg_num = r; }549BasicType type() const { assert(_reg_num == -1 || _reg_num >= LIR_OprDesc::vreg_base, "cannot access type for fixed interval"); return _type; }550void set_type(BasicType type) { assert(_reg_num < LIR_OprDesc::vreg_base || _type == T_ILLEGAL || _type == type, "overwriting existing type"); _type = type; }551552Range* first() const { return _first; }553int from() const { return _first->from(); }554int to() { if (_cached_to == -1) _cached_to = calc_to(); assert(_cached_to == calc_to(), "invalid cached value"); return _cached_to; }555556#ifndef PRODUCT557int num_use_positions() const { return _use_pos_and_kinds.length() / 2; }558#endif559560Interval* next() const { return _next; }561Interval** next_addr() { return &_next; }562void set_next(Interval* next) { _next = next; }563564int assigned_reg() const { return _assigned_reg; }565int assigned_regHi() const { return _assigned_regHi; }566void assign_reg(int reg) { _assigned_reg = reg; _assigned_regHi = LinearScan::any_reg; }567void assign_reg(int reg,int regHi) { _assigned_reg = reg; _assigned_regHi = regHi; }568569Interval* register_hint(bool search_split_child = true) const; // calculation needed570void set_register_hint(Interval* i) { _register_hint = i; }571572int state() const { return _state; }573void set_state(IntervalState s) { _state = s; }574575// access to split parent and split children576bool is_split_parent() const { return _split_parent == this; }577bool is_split_child() const { return _split_parent != this; }578Interval* split_parent() const { assert(_split_parent->is_split_parent(), "must be"); return _split_parent; }579Interval* split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode);580Interval* split_child_before_op_id(int op_id);581DEBUG_ONLY(void check_split_children();)582583// information stored in split parent, but available for all children584int canonical_spill_slot() const { return split_parent()->_canonical_spill_slot; }585void set_canonical_spill_slot(int slot) { assert(split_parent()->_canonical_spill_slot == -1, "overwriting existing value"); split_parent()->_canonical_spill_slot = slot; }586Interval* current_split_child() const { return split_parent()->_current_split_child; }587void make_current_split_child() { split_parent()->_current_split_child = this; }588589bool insert_move_when_activated() const { return _insert_move_when_activated; }590void set_insert_move_when_activated(bool b) { _insert_move_when_activated = b; }591592// for spill optimization593IntervalSpillState spill_state() const { return split_parent()->_spill_state; }594int spill_definition_pos() const { return split_parent()->_spill_definition_pos; }595void set_spill_state(IntervalSpillState state) { assert(state >= spill_state(), "state cannot decrease"); split_parent()->_spill_state = state; }596void set_spill_definition_pos(int pos) { assert(spill_definition_pos() == -1, "cannot set the position twice"); split_parent()->_spill_definition_pos = pos; }597// returns true if this interval has a shadow copy on the stack that is always correct598bool always_in_memory() const { return split_parent()->_spill_state == storeAtDefinition || split_parent()->_spill_state == startInMemory; }599600// caching of values that take time to compute and are used multiple times601LIR_Opr cached_opr() const { return _cached_opr; }602VMReg cached_vm_reg() const { return _cached_vm_reg; }603void set_cached_opr(LIR_Opr opr) { _cached_opr = opr; }604void set_cached_vm_reg(VMReg reg) { _cached_vm_reg = reg; }605606// access to use positions607int first_usage(IntervalUseKind min_use_kind) const; // id of the first operation requiring this interval in a register608int next_usage(IntervalUseKind min_use_kind, int from) const; // id of next usage seen from the given position609int next_usage_exact(IntervalUseKind exact_use_kind, int from) const;610int previous_usage(IntervalUseKind min_use_kind, int from) const;611612// manipulating intervals613void add_use_pos(int pos, IntervalUseKind use_kind);614void add_range(int from, int to);615Interval* split(int split_pos);616Interval* split_from_start(int split_pos);617void remove_first_use_pos() { _use_pos_and_kinds.trunc_to(_use_pos_and_kinds.length() - 2); }618619// test intersection620bool covers(int op_id, LIR_OpVisitState::OprMode mode) const;621bool has_hole_between(int from, int to);622bool intersects(Interval* i) const { return _first->intersects(i->_first); }623bool intersects_any_children_of(Interval* i) const;624int intersects_at(Interval* i) const { return _first->intersects_at(i->_first); }625626// range iteration627void rewind_range() { _current = _first; }628void next_range() { assert(this != _end, "not allowed on sentinel"); _current = _current->next(); }629int current_from() const { return _current->from(); }630int current_to() const { return _current->to(); }631bool current_at_end() const { return _current == Range::end(); }632bool current_intersects(Interval* it) { return _current->intersects(it->_current); };633int current_intersects_at(Interval* it) { return _current->intersects_at(it->_current); };634635// printing636#ifndef PRODUCT637void print() const { print_on(tty); }638void print_on(outputStream* out) const {639print_on(out, false);640}641// Special version for compatibility with C1 Visualizer.642void print_on(outputStream* out, bool is_cfg_printer) const;643644// Used for debugging645void print_parent() const;646void print_children() const;647#endif648649};650651652class IntervalWalker : public CompilationResourceObj {653protected:654Compilation* _compilation;655LinearScan* _allocator;656657Interval* _unhandled_first[nofKinds]; // sorted list of intervals, not life before the current position658Interval* _active_first [nofKinds]; // sorted list of intervals, life at the current position659Interval* _inactive_first [nofKinds]; // sorted list of intervals, intervals in a life time hole at the current position660661Interval* _current; // the current interval coming from unhandled list662int _current_position; // the current position (intercept point through the intervals)663IntervalKind _current_kind; // and whether it is fixed_kind or any_kind.664665666Compilation* compilation() const { return _compilation; }667LinearScan* allocator() const { return _allocator; }668669// unified bailout support670void bailout(const char* msg) const { compilation()->bailout(msg); }671bool bailed_out() const { return compilation()->bailed_out(); }672673void check_bounds(IntervalKind kind) { assert(kind >= fixedKind && kind <= anyKind, "invalid interval_kind"); }674675Interval** unhandled_first_addr(IntervalKind kind) { check_bounds(kind); return &_unhandled_first[kind]; }676Interval** active_first_addr(IntervalKind kind) { check_bounds(kind); return &_active_first[kind]; }677Interval** inactive_first_addr(IntervalKind kind) { check_bounds(kind); return &_inactive_first[kind]; }678679void append_sorted(Interval** first, Interval* interval);680void append_to_unhandled(Interval** list, Interval* interval);681682bool remove_from_list(Interval** list, Interval* i);683void remove_from_list(Interval* i);684685void next_interval();686Interval* current() const { return _current; }687IntervalKind current_kind() const { return _current_kind; }688689void walk_to(IntervalState state, int from);690691// activate_current() is called when an unhandled interval becomes active (in current(), current_kind()).692// Return false if current() should not be moved the the active interval list.693// It is safe to append current to any interval list but the unhandled list.694virtual bool activate_current() { return true; }695696// This method is called whenever an interval moves from one interval list to another to print some697// information about it and its state change if TraceLinearScanLevel is set appropriately.698DEBUG_ONLY(void interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to);)699700public:701IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);702703Interval* unhandled_first(IntervalKind kind) { check_bounds(kind); return _unhandled_first[kind]; }704Interval* active_first(IntervalKind kind) { check_bounds(kind); return _active_first[kind]; }705Interval* inactive_first(IntervalKind kind) { check_bounds(kind); return _inactive_first[kind]; }706707// active contains the intervals that are live after the lir_op708void walk_to(int lir_op_id);709// active contains the intervals that are live before the lir_op710void walk_before(int lir_op_id) { walk_to(lir_op_id-1); }711// walk through all intervals712void walk() { walk_to(max_jint); }713714int current_position() { return _current_position; }715};716717718// The actual linear scan register allocator719class LinearScanWalker : public IntervalWalker {720enum {721any_reg = LinearScan::any_reg722};723724private:725int _first_reg; // the reg. number of the first phys. register726int _last_reg; // the reg. nmber of the last phys. register727int _num_phys_regs; // required by current interval728bool _adjacent_regs; // have lo/hi words of phys. regs be adjacent729730int _use_pos[LinearScan::nof_regs];731int _block_pos[LinearScan::nof_regs];732IntervalList* _spill_intervals[LinearScan::nof_regs];733734MoveResolver _move_resolver; // for ordering spill moves735736// accessors mapped to same functions in class LinearScan737int block_count() const { return allocator()->block_count(); }738BlockBegin* block_at(int idx) const { return allocator()->block_at(idx); }739BlockBegin* block_of_op_with_id(int op_id) const { return allocator()->block_of_op_with_id(op_id); }740741void init_use_lists(bool only_process_use_pos);742void exclude_from_use(int reg);743void exclude_from_use(Interval* i);744void set_use_pos(int reg, Interval* i, int use_pos, bool only_process_use_pos);745void set_use_pos(Interval* i, int use_pos, bool only_process_use_pos);746void set_block_pos(int reg, Interval* i, int block_pos);747void set_block_pos(Interval* i, int block_pos);748749void free_exclude_active_fixed();750void free_exclude_active_any();751void free_collect_inactive_fixed(Interval* cur);752void free_collect_inactive_any(Interval* cur);753void spill_exclude_active_fixed();754void spill_block_inactive_fixed(Interval* cur);755void spill_collect_active_any();756void spill_collect_inactive_any(Interval* cur);757758void insert_move(int op_id, Interval* src_it, Interval* dst_it);759int find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos);760int find_optimal_split_pos(Interval* it, int min_split_pos, int max_split_pos, bool do_loop_optimization);761void split_before_usage(Interval* it, int min_split_pos, int max_split_pos);762void split_for_spilling(Interval* it);763void split_stack_interval(Interval* it);764void split_when_partial_register_available(Interval* it, int register_available_until);765void split_and_spill_interval(Interval* it);766767int find_free_reg(int reg_needed_until, int interval_to, int hint_reg, int ignore_reg, bool* need_split);768int find_free_double_reg(int reg_needed_until, int interval_to, int hint_reg, bool* need_split);769bool alloc_free_reg(Interval* cur);770771int find_locked_reg(int reg_needed_until, int interval_to, int ignore_reg, bool* need_split);772int find_locked_double_reg(int reg_needed_until, int interval_to, bool* need_split);773void split_and_spill_intersecting_intervals(int reg, int regHi);774void alloc_locked_reg(Interval* cur);775776bool no_allocation_possible(Interval* cur);777void init_vars_for_alloc(Interval* cur);778bool pd_init_regs_for_alloc(Interval* cur);779780void combine_spilled_intervals(Interval* cur);781bool is_move(LIR_Op* op, Interval* from, Interval* to);782783bool activate_current();784785public:786LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first);787788// must be called when all intervals are allocated789void finish_allocation() { _move_resolver.resolve_and_append_moves(); }790};791792793794/*795When a block has more than one predecessor, and all predecessors end with796the same sequence of move-instructions, than this moves can be placed once797at the beginning of the block instead of multiple times in the predecessors.798799Similarly, when a block has more than one successor, then equal sequences of800moves at the beginning of the successors can be placed once at the end of801the block. But because the moves must be inserted before all branch802instructions, this works only when there is exactly one conditional branch803at the end of the block (because the moves must be inserted before all804branches, but after all compares).805806This optimization affects all kind of moves (reg->reg, reg->stack and807stack->reg). Because this optimization works best when a block contains only808few moves, it has a huge impact on the number of blocks that are totally809empty.810*/811class EdgeMoveOptimizer : public StackObj {812private:813// the class maintains a list with all lir-instruction-list of the814// successors (predecessors) and the current index into the lir-lists815LIR_OpListStack _edge_instructions;816intStack _edge_instructions_idx;817818void init_instructions();819void append_instructions(LIR_OpList* instructions, int instructions_idx);820LIR_Op* instruction_at(int edge);821void remove_cur_instruction(int edge, bool decrement_index);822823bool operations_different(LIR_Op* op1, LIR_Op* op2);824825void optimize_moves_at_block_end(BlockBegin* cur);826void optimize_moves_at_block_begin(BlockBegin* cur);827828EdgeMoveOptimizer();829830public:831static void optimize(BlockList* code);832};833834835836class ControlFlowOptimizer : public StackObj {837private:838BlockList _original_preds;839840enum {841ShortLoopSize = 5842};843void reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx);844void reorder_short_loops(BlockList* code);845846bool can_delete_block(BlockBegin* cur);847void substitute_branch_target(BlockBegin* cur, BlockBegin* target_from, BlockBegin* target_to);848void delete_empty_blocks(BlockList* code);849850void delete_unnecessary_jumps(BlockList* code);851void delete_jumps_to_return(BlockList* code);852853DEBUG_ONLY(void verify(BlockList* code);)854855ControlFlowOptimizer();856public:857static void optimize(BlockList* code);858};859860861#ifndef PRODUCT862863// Helper class for collecting statistics of LinearScan864class LinearScanStatistic : public StackObj {865public:866enum Counter {867// general counters868counter_method,869counter_fpu_method,870counter_loop_method,871counter_exception_method,872counter_loop,873counter_block,874counter_loop_block,875counter_exception_block,876counter_interval,877counter_fixed_interval,878counter_range,879counter_fixed_range,880counter_use_pos,881counter_fixed_use_pos,882counter_spill_slots,883blank_line_1,884885// counter for classes of lir instructions886counter_instruction,887counter_label,888counter_entry,889counter_return,890counter_call,891counter_move,892counter_cmp,893counter_cond_branch,894counter_uncond_branch,895counter_stub_branch,896counter_alu,897counter_alloc,898counter_sync,899counter_throw,900counter_unwind,901counter_typecheck,902counter_fpu_stack,903counter_misc_inst,904counter_other_inst,905blank_line_2,906907// counter for different types of moves908counter_move_total,909counter_move_reg_reg,910counter_move_reg_stack,911counter_move_stack_reg,912counter_move_stack_stack,913counter_move_reg_mem,914counter_move_mem_reg,915counter_move_const_any,916917number_of_counters,918invalid_counter = -1919};920921private:922int _counters_sum[number_of_counters];923int _counters_max[number_of_counters];924925void inc_counter(Counter idx, int value = 1) { _counters_sum[idx] += value; }926927const char* counter_name(int counter_idx);928Counter base_counter(int counter_idx);929930void sum_up(LinearScanStatistic &method_statistic);931void collect(LinearScan* allocator);932933public:934LinearScanStatistic();935void print(const char* title);936static void compute(LinearScan* allocator, LinearScanStatistic &global_statistic);937};938939940// Helper class for collecting compilation time of LinearScan941class LinearScanTimers : public StackObj {942public:943enum Timer {944timer_do_nothing,945timer_number_instructions,946timer_compute_local_live_sets,947timer_compute_global_live_sets,948timer_build_intervals,949timer_sort_intervals_before,950timer_allocate_registers,951timer_resolve_data_flow,952timer_sort_intervals_after,953timer_eliminate_spill_moves,954timer_assign_reg_num,955timer_allocate_fpu_stack,956timer_optimize_lir,957958number_of_timers959};960961private:962elapsedTimer _timers[number_of_timers];963const char* timer_name(int idx);964965public:966LinearScanTimers();967968void begin_method(); // called for each method when register allocation starts969void end_method(LinearScan* allocator); // called for each method when register allocation completed970void print(double total_time); // called before termination of VM to print global summary971972elapsedTimer* timer(int idx) { return &(_timers[idx]); }973};974975976#endif // ifndef PRODUCT977978// Pick up platform-dependent implementation details979#include CPU_HEADER(c1_LinearScan)980981#endif // SHARE_C1_C1_LINEARSCAN_HPP982983984