1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/cpu/x86/vm/c1_LinearScan_x86.hpp Sat Dec 01 00:00:00 2007 +0000 1.3 @@ -0,0 +1,176 @@ 1.4 +/* 1.5 + * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 1.23 + * CA 95054 USA or visit www.sun.com if you need additional information or 1.24 + * have any questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +inline bool LinearScan::is_processed_reg_num(int reg_num) { 1.29 + // rsp and rbp (numbers 6 ancd 7) are ignored 1.30 + assert(FrameMap::rsp_opr->cpu_regnr() == 6, "wrong assumption below"); 1.31 + assert(FrameMap::rbp_opr->cpu_regnr() == 7, "wrong assumption below"); 1.32 + assert(reg_num >= 0, "invalid reg_num"); 1.33 + 1.34 + return reg_num < 6 || reg_num > 7; 1.35 +} 1.36 + 1.37 +inline int LinearScan::num_physical_regs(BasicType type) { 1.38 + // Intel requires two cpu registers for long, 1.39 + // but requires only one fpu register for double 1.40 + if (type == T_LONG) { 1.41 + return 2; 1.42 + } 1.43 + return 1; 1.44 +} 1.45 + 1.46 + 1.47 +inline bool LinearScan::requires_adjacent_regs(BasicType type) { 1.48 + return false; 1.49 +} 1.50 + 1.51 +inline bool LinearScan::is_caller_save(int assigned_reg) { 1.52 + assert(assigned_reg >= 0 && assigned_reg < nof_regs, "should call this only for registers"); 1.53 + return true; // no callee-saved registers on Intel 1.54 + 1.55 +} 1.56 + 1.57 + 1.58 +inline void LinearScan::pd_add_temps(LIR_Op* op) { 1.59 + switch (op->code()) { 1.60 + case lir_tan: 1.61 + case lir_sin: 1.62 + case lir_cos: { 1.63 + // The slow path for these functions may need to save and 1.64 + // restore all live registers but we don't want to save and 1.65 + // restore everything all the time, so mark the xmms as being 1.66 + // killed. If the slow path were explicit or we could propagate 1.67 + // live register masks down to the assembly we could do better 1.68 + // but we don't have any easy way to do that right now. We 1.69 + // could also consider not killing all xmm registers if we 1.70 + // assume that slow paths are uncommon but it's not clear that 1.71 + // would be a good idea. 1.72 + if (UseSSE > 0) { 1.73 +#ifndef PRODUCT 1.74 + if (TraceLinearScanLevel >= 2) { 1.75 + tty->print_cr("killing XMMs for trig"); 1.76 + } 1.77 +#endif 1.78 + int op_id = op->id(); 1.79 + for (int xmm = 0; xmm < FrameMap::nof_caller_save_xmm_regs; xmm++) { 1.80 + LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(xmm); 1.81 + add_temp(reg_num(opr), op_id, noUse, T_ILLEGAL); 1.82 + } 1.83 + } 1.84 + break; 1.85 + } 1.86 + } 1.87 +} 1.88 + 1.89 + 1.90 +// Implementation of LinearScanWalker 1.91 + 1.92 +inline bool LinearScanWalker::pd_init_regs_for_alloc(Interval* cur) { 1.93 + if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::byte_reg)) { 1.94 + assert(cur->type() != T_FLOAT && cur->type() != T_DOUBLE, "cpu regs only"); 1.95 + _first_reg = pd_first_byte_reg; 1.96 + _last_reg = pd_last_byte_reg; 1.97 + return true; 1.98 + } else if ((UseSSE >= 1 && cur->type() == T_FLOAT) || (UseSSE >= 2 && cur->type() == T_DOUBLE)) { 1.99 + _first_reg = pd_first_xmm_reg; 1.100 + _last_reg = pd_last_xmm_reg; 1.101 + return true; 1.102 + } 1.103 + 1.104 + return false; 1.105 +} 1.106 + 1.107 + 1.108 +class FpuStackAllocator VALUE_OBJ_CLASS_SPEC { 1.109 + private: 1.110 + Compilation* _compilation; 1.111 + LinearScan* _allocator; 1.112 + 1.113 + LIR_OpVisitState visitor; 1.114 + 1.115 + LIR_List* _lir; 1.116 + int _pos; 1.117 + FpuStackSim _sim; 1.118 + FpuStackSim _temp_sim; 1.119 + 1.120 + bool _debug_information_computed; 1.121 + 1.122 + LinearScan* allocator() { return _allocator; } 1.123 + Compilation* compilation() const { return _compilation; } 1.124 + 1.125 + // unified bailout support 1.126 + void bailout(const char* msg) const { compilation()->bailout(msg); } 1.127 + bool bailed_out() const { return compilation()->bailed_out(); } 1.128 + 1.129 + int pos() { return _pos; } 1.130 + void set_pos(int pos) { _pos = pos; } 1.131 + LIR_Op* cur_op() { return lir()->instructions_list()->at(pos()); } 1.132 + LIR_List* lir() { return _lir; } 1.133 + void set_lir(LIR_List* lir) { _lir = lir; } 1.134 + FpuStackSim* sim() { return &_sim; } 1.135 + FpuStackSim* temp_sim() { return &_temp_sim; } 1.136 + 1.137 + int fpu_num(LIR_Opr opr); 1.138 + int tos_offset(LIR_Opr opr); 1.139 + LIR_Opr to_fpu_stack_top(LIR_Opr opr, bool dont_check_offset = false); 1.140 + 1.141 + // Helper functions for handling operations 1.142 + void insert_op(LIR_Op* op); 1.143 + void insert_exchange(int offset); 1.144 + void insert_exchange(LIR_Opr opr); 1.145 + void insert_free(int offset); 1.146 + void insert_free_if_dead(LIR_Opr opr); 1.147 + void insert_free_if_dead(LIR_Opr opr, LIR_Opr ignore); 1.148 + void insert_copy(LIR_Opr from, LIR_Opr to); 1.149 + void do_rename(LIR_Opr from, LIR_Opr to); 1.150 + void do_push(LIR_Opr opr); 1.151 + void pop_if_last_use(LIR_Op* op, LIR_Opr opr); 1.152 + void pop_always(LIR_Op* op, LIR_Opr opr); 1.153 + void clear_fpu_stack(LIR_Opr preserve); 1.154 + void handle_op1(LIR_Op1* op1); 1.155 + void handle_op2(LIR_Op2* op2); 1.156 + void handle_opCall(LIR_OpCall* opCall); 1.157 + void compute_debug_information(LIR_Op* op); 1.158 + void allocate_exception_handler(XHandler* xhandler); 1.159 + void allocate_block(BlockBegin* block); 1.160 + 1.161 +#ifndef PRODUCT 1.162 + void check_invalid_lir_op(LIR_Op* op); 1.163 +#endif 1.164 + 1.165 + // Helper functions for merging of fpu stacks 1.166 + void merge_insert_add(LIR_List* instrs, FpuStackSim* cur_sim, int reg); 1.167 + void merge_insert_xchg(LIR_List* instrs, FpuStackSim* cur_sim, int slot); 1.168 + void merge_insert_pop(LIR_List* instrs, FpuStackSim* cur_sim); 1.169 + bool merge_rename(FpuStackSim* cur_sim, FpuStackSim* sux_sim, int start_slot, int change_slot); 1.170 + void merge_fpu_stack(LIR_List* instrs, FpuStackSim* cur_sim, FpuStackSim* sux_sim); 1.171 + void merge_cleanup_fpu_stack(LIR_List* instrs, FpuStackSim* cur_sim, BitMap& live_fpu_regs); 1.172 + bool merge_fpu_stack_with_successors(BlockBegin* block); 1.173 + 1.174 + public: 1.175 + LIR_Opr to_fpu_stack(LIR_Opr opr); // used by LinearScan for creation of debug information 1.176 + 1.177 + FpuStackAllocator(Compilation* compilation, LinearScan* allocator); 1.178 + void allocate(); 1.179 +};