filename | src/xlat/regalloc.c |
changeset | 1011:fdd58619b760 |
author | nkeynes |
date | Sun Apr 12 07:24:45 2009 +0000 (14 years ago) |
branch | xlat-refactor |
permissions | -rw-r--r-- |
last change | Restructure operand types - rename to forms to avoid conflict for actual data types temporary operands are now a first class form remove explicit types for immediates - now implied by opcode Initial work on promote-source-reg pass |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/xlat/regalloc.c Sun Apr 12 07:24:45 2009 +00001.3 @@ -0,0 +1,108 @@1.4 +/**1.5 + * $Id: regalloc.h 931 2008-10-31 02:57:59Z nkeynes $1.6 + *1.7 + * Register allocation based on simple linear scan1.8 + *1.9 + * Copyright (c) 2008 Nathan Keynes.1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.14 + * (at your option) any later version.1.15 + *1.16 + * This program is distributed in the hope that it will be useful,1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.19 + * GNU General Public License for more details.1.20 + */1.21 +1.22 +#include <stdlib.h>1.23 +#include <string.h>1.24 +#include "lxdream.h"1.25 +#include "xir.h"1.26 +1.27 +1.28 +/**1.29 + * Promote all source registers to temporaries, in preparation for regalloc.1.30 + * In case of partial aliasing, we flush back to memory before reloading (this1.31 + * needs to be improved)1.32 + */1.33 +void xir_promote_source_registers( xir_basic_block_t xbb, xir_op_t start, xir_op_t end )1.34 +{1.35 + struct temp_reg {1.36 + gboolean is_dirty;1.37 + xir_op_t last_access;1.38 + };1.39 +1.40 + struct temp_reg all_temp_regs[MAX_TEMP_REGISTER+1];1.41 +1.42 +1.43 + /* -1 if byte is not allocated to a temporary, otherwise temp id */1.44 + int16_t source_regs[MAX_SOURCE_REGISTER+1];1.45 +1.46 + memset( source_regs, -1, sizeof(source_regs) );1.47 + memset( all_temp_regs, 0, sizeof(all_temp_regs) );1.48 +1.49 + for( xir_op_t it = start; it != NULL; it = it->next ) {1.50 + if( XOP_IS_SRC(it,0) ) {1.51 + int r = XOP_REG(it,0);1.52 + int s = XOP_OPSIZE(it,0);1.53 + int t = source_regs[r];1.54 + if( t == -1 ) {1.55 + t = xir_alloc_temp_reg( xbb, XOP_OPTYPE(it,0), r );1.56 + source_regs[r] = t;1.57 + if( XOP_READS_OP1(it) ) {1.58 + xir_insert_op( XOP2ST( OP_MOV, r, t ), it );1.59 + }1.60 + }1.61 + it->operand[0].form = TEMP_OPERAND;1.62 + it->operand[0].value.i = t;1.63 + all_temp_regs[t].last_access = it;1.64 + all_temp_regs[t].is_dirty |= XOP_WRITES_OP1(it);1.65 + }1.66 +1.67 + if( XOP_IS_SRC(it,1) ) {1.68 + int r = XOP_REG(it,1);1.69 + int s = XOP_OPSIZE(it,1);1.70 + int t = source_regs[r];1.71 + if( t == -1 ) {1.72 + t = xir_alloc_temp_reg( xbb, XOP_OPTYPE(it,1), r );1.73 + source_regs[r] = t;1.74 + if( XOP_READS_OP2(it) ) {1.75 + xir_insert_op( XOP2ST( OP_MOV, r, t ), it );1.76 + }1.77 + }1.78 + it->operand[1].form = TEMP_OPERAND;1.79 + it->operand[1].value.i = t;1.80 + all_temp_regs[t].last_access = it;1.81 + all_temp_regs[t].is_dirty |= XOP_WRITES_OP2(it);1.82 + }1.83 +1.84 + if( it == end )1.85 + break;1.86 + }1.87 +1.88 + for( int i=0; i<xbb->next_temp_reg; i++ ) {1.89 + if( all_temp_regs[i].last_access != NULL && all_temp_regs[i].is_dirty ) {1.90 + xir_insert_op( XOP2TS( OP_MOV, i, xbb->temp_regs[i].home_register ),1.91 + all_temp_regs[i].last_access->next );1.92 + }1.93 + }1.94 +}1.95 +1.96 +1.97 +/**1.98 + * General constraints:1.99 + * Temporaries can't be spilled, must be held in a target register1.100 + *1.101 + * 3 categories of target register:1.102 + * Argument (ie EAX/EDX for ia32): assign call arguments to appropriate regs1.103 + * first. Any available lifetime rolls over to the general volatile regs1.104 + * Volatile (caller-saved): Assign variables with lifetime between calls first1.105 + * Non-volatile (callee-saved): Everything else with cost-balancing (each1.106 + * register used costs the equivalent of a spill/unspill pair)1.107 + *1.108 + * For x86, argument regs are EAX + EDX, ECX is volatile, and ESI/EDI/EBX are non-volatile.1.109 + * For x86-64, arguments regs are EDI + ESI, EBX, R8-R11 are volatile, and R12-R15 are non-volatile.1.110 + * (ESP+EBP are reserved either way)1.111 + */1.112 \ No newline at end of file
.