----- Original Message ---- > From: Ian Lance Taylor <i...@google.com> > To: Jamie Prescott <jpre...@yahoo.com> > Cc: gcc@gcc.gnu.org > Sent: Thursday, May 14, 2009 10:09:40 PM > Subject: Re: Compact regsiter allocation > > Jamie Prescott writes: > > > If not, what is the best spot (in the normal GCC target hooks) to trigger > > it? > Where the > > full insn tree is passed in such hook (if it's not a global)? > > TARGET_MACHINE_DEPENDENT_REORG. It will be invoked once for each > function, and can access and modify the complete RTL insn tree.
It wasn't as easy as I expected. Likely because my knowledge of GCC internals is pretty shallow. This is what I came up with. The target reorg is great, but it had two problems for me. One is that it was issued after the prologue/epilogue, where I had to emit insns based on the already-remapped status, so I ended up keeping as hash of non-remappable instructions that I fed with the xxx_emit_hashed_insn(). I use the hash to detect which insns do not have to be remapped. Not only, since REG RTXs can appear multiple times, I need to feed the RTX into the hash, after having been remapped once. This seems to be working fine, but my biggest doubt is that way I dig into the single instructions to find REG RTXs to remap. I looked around and I ended up with the code below, partially stolen from print_rtx(). Is there a public/non-hackish API to enum all the RTXs contained inside an instruction? If not, do I handle all the possible cases in xxx_enum_rtx()? Seem code below, with xxx_reorg() being my reorg function ... - Jamie typedef struct s_xxx_reg_remap { int from, to; } xxx_reg_remap_t; static void xxx_remap_reg(rtx insn, xxx_reg_remap_t const *rmap, int n) { int i, regno = REGNO(insn); if (xxx_ptrhash_lookup(&insns_hash, (void *) insn, NULL)) return; for (i = 0; i < n; i++) if (rmap[i].from == regno) { xxx_ptrhash_add(&insns_hash, (void *) insn); SET_REGNO(insn, rmap[i].to); break; } } static void xxx_enum_rtx(rtx insn, xxx_reg_remap_t const *rmap, int n, void (*proc)(rtx, xxx_reg_remap_t const *, int)) { int i, j, len, vlen; char const *fmt; rtx x, y; if (xxx_ptrhash_lookup(&insns_hash, (void *) insn, NULL)) return; fmt = GET_RTX_FORMAT(GET_CODE(insn)); len = GET_RTX_LENGTH(GET_CODE(insn)); for (i = 0; i < len; i++, fmt++) { switch (*fmt) { case 'e': if ((x = XEXP(insn, i)) == NULL_RTX) continue; if (GET_CODE(x) == REG) (*proc)(x, rmap, n); else xxx_enum_rtx(x, rmap, n, proc); break; case 'E': case 'V': if (XVEC(insn, i) == NULL) break; vlen = XVECLEN(insn, i); for (j = 0; j < vlen; j++) { if ((y = XVECEXP(insn, i, j)) != NULL_RTX) xxx_enum_rtx(y, rmap, n, proc); } break; } } } static void xxx_reorg(void) { rtx insn; insn = get_insns(); gcc_assert(GET_CODE(insn) == NOTE); for (insn = next_nonnote_insn(insn); insn != NULL_RTX; insn = next_nonnote_insn(insn)) { xxx_enum_rtx(insn, func_rmap, func_nrmap, xxx_remap_reg); } xxx_ptrhash_free(&insns_hash); } static rtx xxx_emit_hashed_insn(rtx insn) { xxx_ptrhash_add(&insns_hash, (void *) insn); return emit_insn(insn); }