peepc30.c
来自「一款拥有一定历史的C语言编译器」· C语言 代码 · 共 2,250 行 · 第 1/5 页
C
2,250 行
case am_const_direct: return is_equalnode (ap1->u.offset, ap2->u.offset); default: break; } return FALSE;}static BOOL is_equal_oper P2 (const ADDRESS *, ap1, const ADDRESS *, ap2){ if (ap1 == NIL_ADDRESS && ap2 == NIL_ADDRESS) return TRUE; if (ap1 == NIL_ADDRESS || ap2 == NIL_ADDRESS) return FALSE; if (ap1->mode != ap2->mode) return FALSE; switch (ap1->mode) { case am_areg: case am_dreg: case am_freg: case am_ireg: case am_sreg: case am_ind: case am_const_ind: return ap1->preg == ap2->preg; case am_indx: case am_ainc: case am_adec: case am_preinc: case am_predec: return ap1->preg == ap2->preg && is_equalnode (ap1->u.offset, ap2->u.offset); case am_indx2: case am_indxs: return ap1->preg == ap2->preg && ap1->sreg == ap2->sreg; case am_direct: case am_const_direct: case am_immed: return is_equalnode (ap1->u.offset, ap2->u.offset); case am_none: case am_line: return TRUE; default: break; } return FALSE;}/* * Builds the peepinfo of this instruction. */void build_register_map P2 (const CODE *, ip, PEEPINFO *, map){ ADDRESS *src[4]; ADDRESS *dst[2]; ADDRESS *ap; int i; if (map == NULL) { FATAL ((__FILE__, "build_register_map", "NULL-Pointer")); } src[0] = ip->src1; src[1] = ip->src2; src[2] = ip->src21; src[3] = ip->src22; dst[0] = ip->dst; dst[1] = ip->dst2; map->write = 0; map->modified = 0; map->read = 0; map->used = 0; map->updated = 0;#ifdef REGISTER_FLOW_ANALYZER map->used_later = 0; map->fixed = 0;#endif /* REGISTER_FLOW_ANALYZER */ for (i = 0; i < 4; i++) { if ((ap = src[i]) != NIL_ADDRESS) { switch (ap->mode) { case am_areg: case am_ireg: case am_dreg: case am_freg: case am_sreg: map->read |= (1UL << (int) ap->preg); break; case am_ainc: case am_adec: case am_preinc: case am_predec: map->updated |= (1UL << (int) ap->preg); map->read |= (1UL << REG_MEMORY); break; case am_indx2: case am_indxs: map->used |= (1UL << (int) ap->sreg); /*lint -fallthrough */ case am_ind: case am_const_ind: case am_indx: map->used |= (1UL << (int) ap->preg); /*lint -fallthrough */ case am_direct: case am_const_direct: /*lint -fallthrough */ map->read |= (1UL << REG_MEMORY); break; default: break; } } } for (i = 0; i < 2; i++) { if ((ap = dst[i]) != NIL_ADDRESS) { switch (ap->mode) { case am_areg: case am_ireg: case am_dreg: case am_freg: case am_sreg: map->modified |= (1UL << (int) ap->preg);#if 0 /* * stack and normal memory should not interfere each other * i.e. modification of SP should not invalidate still * used memory, else we have some problems anyway */ if (ap->preg == REG_SP) { /* if we change sp, we dont know what hapens with memory */ map->modified |= (1UL << REG_MEMORY); }#endif break; case am_ainc: case am_adec: case am_preinc: case am_predec: map->updated |= (1UL << (int) ap->preg); map->modified |= (1UL << REG_MEMORY); break; case am_indx2: case am_indxs: map->used |= (1UL << (int) ap->sreg); /*lint -fallthrough */ case am_ind: case am_const_ind: case am_indx: map->used |= (1UL << (int) ap->preg); /*lint -fallthrough */ case am_direct: case am_const_direct: /*lint -fallthrough */ map->modified |= (1UL << REG_MEMORY); break; default: break; } } } if (is_dest_overwritten (ip->opcode)) { map->write = map->modified; map->modified = 0; } if (is_using_sp (ip->opcode)) { map->updated |= (1UL << REG_SP); /* if we change sp, we dont know what hapens with memory */ /* * 29.07.96 * call, push, pop's should never change memory we are * using in other addressingmodes * so dont mark memory as modified * * map->modified |= (1UL<<REG_MEMORY); */ }#ifdef PEEP_CALL_ALSO_VIA_TABLE if ((ip->opcode == op_call) || (ip->opcode == op_callu) || (ip->opcode == op_xcall) || (ip->opcode == op_trapu)) { for (i = REG_R0; i <= MAX_DATA; i++) { map->write |= 1UL << i; } for (i = REG_AR0; i <= MAX_ADDR; i++) { map->write |= 1UL << i; } if (ip->opcode == op_xcall) { map->read = (1UL << REG_R0) | (1UL << REG_R1); } }#endif /* PEEP_CALL_ALSO_VIA_TABLE */}/* * Attaches a peepoinfo to an instruction. */#ifndef SAVE_PEEP_MEMORYstatic void attach_peepinfo_fkt P1 (CODE *, ip){ PEEPINFO *map = (PEEPINFO *) xalloc ((size_t) sizeof (PEEPINFO)); build_register_map (ip, map); ip->info = map;}void update_peepinfo_fkt P1 (CODE *, ip){ build_register_map (ip, ip->info);}#endif /* SAVE_PEEP_MEMORY *//* * Checks if instruction 'ip1' may be moved before instruction * 'ip2', ie If both instructions are independent * (both may have the same sources, but the destination or modified * address register of the one is not to be used by the other). */static BOOL is_ip_swap_possible P2 (const CODE *, ip1, const CODE *, ip2){ REGBITMAP changed1, changed2; REGBITMAP needed1, needed2;#ifndef SAVE_PEEP_MEMORY PEEPINFO *map1, *map2; map1 = ip1->info; map2 = ip2->info; /* * all registers which are modified in any way in one instruction * may not be used in any way by the other instruction */ changed1 = map1->modified | map1->updated | map1->write; changed2 = map2->modified | map2->updated | map2->write; needed1 = map1->modified | map1->updated | map1->read | map1->used; needed2 = map2->modified | map2->updated | map2->read | map2->used;#else /* SAVE_PEEP_MEMORY */ PEEPINFO map1, map2; build_register_map (ip1, &map1); build_register_map (ip2, &map2); /* * all registers which are modified in any way in one instruction * may not be used in any way by the other instruction */ changed1 = map1.modified | map1.updated | map1.write; changed2 = map2.modified | map2.updated | map2.write; needed1 = map1.modified | map1.updated | map1.read | map1.used; needed2 = map2.modified | map2.updated | map2.read | map2.used;#endif /* SAVE_PEEP_MEMORY */ /* * we do not want to swap instructions who changes the stack * with instructions who access memory, else we may get a chaos * * for example * * ldi *ar2, r0 * subi 4, sp * * is not save to swapp, ar2 may point to one of the 4 words * behind sp, which are no longer valid after the subi instruction * */ if (changed1 & (1UL << REG_SP)) { changed1 |= (1UL << REG_MEMORY); } if (changed2 & (1UL << REG_SP)) { changed2 |= (1UL << REG_MEMORY); } if (((changed1 & needed2) == 0) && ((changed2 & needed1) == 0)) { return (TRUE); } else {#ifdef PEEP_REDUNDANT_STI if (((changed1 & needed2) | (changed2 & needed1)) == (1UL << REG_MEMORY)) { if (((changed1 & (1UL << REG_SP)) == 0) && ((changed2 & (1UL << REG_SP)) == 0) && (is_memoryaccess_independent (ip1->dst, ip2->src1)) && (is_memoryaccess_independent (ip1->dst, ip2->src2)) && (is_memoryaccess_independent (ip1->dst2, ip2->src21)) && (is_memoryaccess_independent (ip1->dst2, ip2->src22)) && (is_memoryaccess_independent (ip2->dst, ip1->src1)) && (is_memoryaccess_independent (ip2->dst, ip1->src2)) && (is_memoryaccess_independent (ip2->dst2, ip1->src21)) && (is_memoryaccess_independent (ip2->dst2, ip1->src22))) { return TRUE; } }#endif return (FALSE); }}/* * Sets instuctionsflags for given instruction, simplifies * the work for the peephole-optimizer. */static void set_peepflags P1 (CODE *, ip){ ADDRESS *src[4]; ADDRESS *dst[2]; ADDRESS *ap; int i; src[0] = ip->src1; src[1] = ip->src2; src[2] = ip->src21; src[3] = ip->src22; dst[0] = ip->dst; dst[1] = ip->dst2; ip->flags = 0; for (i = 0; i < 4; i++) { if ((ap = src[i]) != NIL_ADDRESS) { switch (ap->mode) { case am_areg: ip->flags |= PEEP_AREG; break; case am_ireg: ip->flags |= PEEP_IREG; break; case am_ainc: case am_adec: case am_preinc: case am_predec: ip->flags |= PEEP_AINC; break; case am_ind: case am_const_ind: case am_indx: ip->flags |= PEEP_IND; break; case am_indx2: case am_indxs: ip->flags |= PEEP_INDEX; break; case am_direct: case am_const_direct: ip->flags |= PEEP_DIRECT; break; case am_sreg: if (ap->preg == REG_SP) { ip->flags |= PEEP_SP; } break; default: break; } } } for (i = 0; i < 2; i++) { if ((ap = dst[i]) != NIL_ADDRESS) { switch (ap->mode) { case am_areg: ip->flags |= PEEP_DST_AREG; break; case am_ireg: ip->flags |= PEEP_DST_IREG; break; case am_ainc: case am_adec: case am_preinc: case am_predec: ip->flags |= PEEP_DST_AINC; break; case am_ind: case am_const_ind: case am_indx: ip->flags |= PEEP_DST_IND; break; case am_indx2: case am_indxs: ip->flags |= PEEP_DST_INDEX; break; case am_direct: case am_const_direct: ip->flags |= PEEP_DST_DIRECT; break; case am_sreg: if (ap->preg == REG_SP) { ip->flags |= PEEP_DST_SP; } break; default: break; } } } if (is_controltransfer (ip->opcode)) { ip->flags |= PEEP_TRANSFER; } if (is_set_all_flags (ip->opcode)) { ip->flags |= PEEP_COMPARE; }}/* * Global code analysis, search for all sorts of pipeline conflicts * and reports them (mainly used for statistical analysis of * the optimizerperformance). */static void analyze_code P4 (int *, totsize, int *, branchconflicts, int *, registerconflicts, int *, asmstatements){ CODE *ip; int tot = 0; int branches = 0; int reg = 0; int asmstat = 0; int group1blocked = 0; int group3blocked = 0; REGBITMAP flags; PEEPINFO *map;#ifdef SAVE_PEEP_MEMORY PEEPINFO StaticMemory;#endif /* SAVE_PEEP_MEMORY */ for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { switch (ip->opcode) { case op_callu: case op_call: case op_trapu: case op_xcall: case op_retiu: case op_retsu:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?