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 + -
显示快捷键?