duke@435: /* xdono@772: * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: inline bool LinearScan::is_processed_reg_num(int reg_num) { never@739: #ifndef _LP64 duke@435: // rsp and rbp (numbers 6 ancd 7) are ignored duke@435: assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below"); duke@435: assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below"); duke@435: assert(reg_num >= 0, "invalid reg_num"); duke@435: duke@435: return reg_num < 6 || reg_num > 7; never@739: #else never@739: // rsp and rbp, r10, r15 (numbers 6 ancd 7) are ignored never@739: assert(FrameMap::r10_opr->cpu_regnr() == 12, "wrong assumption below"); never@739: assert(FrameMap::r15_opr->cpu_regnr() == 13, "wrong assumption below"); never@739: assert(FrameMap::rsp_opr->cpu_regnrLo() == 14, "wrong assumption below"); never@739: assert(FrameMap::rbp_opr->cpu_regnrLo() == 15, "wrong assumption below"); never@739: assert(reg_num >= 0, "invalid reg_num"); never@739: never@739: return reg_num < 12 || reg_num > 15; never@739: #endif // _LP64 duke@435: } duke@435: duke@435: inline int LinearScan::num_physical_regs(BasicType type) { duke@435: // Intel requires two cpu registers for long, duke@435: // but requires only one fpu register for double never@739: if (LP64_ONLY(false &&) type == T_LONG) { duke@435: return 2; duke@435: } duke@435: return 1; duke@435: } duke@435: duke@435: duke@435: inline bool LinearScan::requires_adjacent_regs(BasicType type) { duke@435: return false; duke@435: } duke@435: duke@435: inline bool LinearScan::is_caller_save(int assigned_reg) { duke@435: assert(assigned_reg >= 0 && assigned_reg < nof_regs, "should call this only for registers"); duke@435: return true; // no callee-saved registers on Intel duke@435: duke@435: } duke@435: duke@435: duke@435: inline void LinearScan::pd_add_temps(LIR_Op* op) { duke@435: switch (op->code()) { duke@435: case lir_tan: duke@435: case lir_sin: duke@435: case lir_cos: { duke@435: // The slow path for these functions may need to save and duke@435: // restore all live registers but we don't want to save and duke@435: // restore everything all the time, so mark the xmms as being duke@435: // killed. If the slow path were explicit or we could propagate duke@435: // live register masks down to the assembly we could do better duke@435: // but we don't have any easy way to do that right now. We duke@435: // could also consider not killing all xmm registers if we duke@435: // assume that slow paths are uncommon but it's not clear that duke@435: // would be a good idea. duke@435: if (UseSSE > 0) { duke@435: #ifndef PRODUCT duke@435: if (TraceLinearScanLevel >= 2) { duke@435: tty->print_cr("killing XMMs for trig"); duke@435: } duke@435: #endif duke@435: int op_id = op->id(); duke@435: for (int xmm = 0; xmm < FrameMap::nof_caller_save_xmm_regs; xmm++) { duke@435: LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(xmm); duke@435: add_temp(reg_num(opr), op_id, noUse, T_ILLEGAL); duke@435: } duke@435: } duke@435: break; duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: // Implementation of LinearScanWalker duke@435: duke@435: inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { duke@435: if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) { duke@435: assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); duke@435: _first_reg = pd_first_byte_reg; duke@435: _last_reg = pd_last_byte_reg; duke@435: return true; duke@435: } else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) { duke@435: _first_reg = pd_first_xmm_reg; duke@435: _last_reg = pd_last_xmm_reg; duke@435: return true; duke@435: } duke@435: duke@435: return false; duke@435: } duke@435: duke@435: duke@435: class FpuStackAllocator VALUE_OBJ_CLASS_SPEC { duke@435: private: duke@435: Compilation* _compilation; duke@435: LinearScan* _allocator; duke@435: duke@435: LIR_OpVisitState visitor; duke@435: duke@435: LIR_List* _lir; duke@435: int _pos; duke@435: FpuStackSim _sim; duke@435: FpuStackSim _temp_sim; duke@435: duke@435: bool _debug_information_computed; duke@435: duke@435: LinearScan* allocator() { return _allocator; } duke@435: Compilation* compilation() const { return _compilation; } duke@435: duke@435: // unified bailout support duke@435: void bailout(const char* msg) const { compilation()->bailout(msg); } duke@435: bool bailed_out() const { return compilation()->bailed_out(); } duke@435: duke@435: int pos() { return _pos; } duke@435: void set_pos(int pos) { _pos = pos; } duke@435: LIR_Op* cur_op() { return lir()->instructions_list()->at(pos()); } duke@435: LIR_List* lir() { return _lir; } duke@435: void set_lir(LIR_List* lir) { _lir = lir; } duke@435: FpuStackSim* sim() { return &_sim; } duke@435: FpuStackSim* temp_sim() { return &_temp_sim; } duke@435: duke@435: int fpu_num(LIR_Opr opr); duke@435: int tos_offset(LIR_Opr opr); duke@435: LIR_Opr to_fpu_stack_top(LIR_Opr opr, bool dont_check_offset = false); duke@435: duke@435: // Helper functions for handling operations duke@435: void insert_op(LIR_Op* op); duke@435: void insert_exchange(int offset); duke@435: void insert_exchange(LIR_Opr opr); duke@435: void insert_free(int offset); duke@435: void insert_free_if_dead(LIR_Opr opr); duke@435: void insert_free_if_dead(LIR_Opr opr, LIR_Opr ignore); duke@435: void insert_copy(LIR_Opr from, LIR_Opr to); duke@435: void do_rename(LIR_Opr from, LIR_Opr to); duke@435: void do_push(LIR_Opr opr); duke@435: void pop_if_last_use(LIR_Op* op, LIR_Opr opr); duke@435: void pop_always(LIR_Op* op, LIR_Opr opr); duke@435: void clear_fpu_stack(LIR_Opr preserve); duke@435: void handle_op1(LIR_Op1* op1); duke@435: void handle_op2(LIR_Op2* op2); duke@435: void handle_opCall(LIR_OpCall* opCall); duke@435: void compute_debug_information(LIR_Op* op); duke@435: void allocate_exception_handler(XHandler* xhandler); duke@435: void allocate_block(BlockBegin* block); duke@435: duke@435: #ifndef PRODUCT duke@435: void check_invalid_lir_op(LIR_Op* op); duke@435: #endif duke@435: duke@435: // Helper functions for merging of fpu stacks duke@435: void merge_insert_add(LIR_List* instrs, FpuStackSim* cur_sim, int reg); duke@435: void merge_insert_xchg(LIR_List* instrs, FpuStackSim* cur_sim, int slot); duke@435: void merge_insert_pop(LIR_List* instrs, FpuStackSim* cur_sim); duke@435: bool merge_rename(FpuStackSim* cur_sim, FpuStackSim* sux_sim, int start_slot, int change_slot); duke@435: void merge_fpu_stack(LIR_List* instrs, FpuStackSim* cur_sim, FpuStackSim* sux_sim); duke@435: void merge_cleanup_fpu_stack(LIR_List* instrs, FpuStackSim* cur_sim, BitMap& live_fpu_regs); duke@435: bool merge_fpu_stack_with_successors(BlockBegin* block); duke@435: duke@435: public: duke@435: LIR_Opr to_fpu_stack(LIR_Opr opr); // used by LinearScan for creation of debug information duke@435: duke@435: FpuStackAllocator(Compilation* compilation, LinearScan* allocator); duke@435: void allocate(); duke@435: };