📄 peepx86.c
字号:
#ifdef ASM case op_asm:#endif /* ASM */ return FALSE; case op_line: break; default: if (is_same_instruction (ip, ip2)) { return TRUE; } altered = (BOOL) (op_flags[ip2->opcode] & DEST_ALTERED); overwritten = (BOOL) (op_flags[ip2->opcode] & DEST_OVERWRITE); if (ip2->oper2) { /* two operand instruction */ if (is_equal_address (ip->oper1, ip2->oper2)) { if (overwritten && (ip->length <= ip2->length) && is_equal_address (ip->oper2, ip2->oper1)) return TRUE; if (altered) { return FALSE; } } if (altered && is_address_used (ip2->oper2, ip->oper1)) { return FALSE; } switch (ip2->oper2->mode) { case am_dreg: case am_areg: case am_mreg: case am_direct: case am_immed: if (altered && (is_equal_address (ip->oper2, ip2->oper2) || is_equal_address (ip->oper1, ip2->oper2))) { return FALSE; } break; case am_ind: case am_indx: if (altered && memory) { return FALSE; } break; default: break; } } if (ip2->oper1) { switch (ip2->oper1->mode) { case am_dreg: case am_areg: case am_mreg: case am_direct: case am_immed: if (ip2->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && (is_equal_address (ip->oper2, ip2->oper1) || is_equal_address (ip->oper1, ip2->oper1))) return FALSE; break; case am_ind: case am_indx: if (ip2->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && memory) { return FALSE; } break; default: break; } } break; } } return FALSE;}/* ensure we have a label to branch to (create if needed) */static void check_label P2 (CODE *, ip, CODE *, target){ if (target->fwd->opcode == op_label) { ip->oper1->u.offset->v.l = target->fwd->oper1->u.offset->v.l; } else { CODE *p; p = code (op_label, IL0, mk_label (nextlabel), NIL_ADDRESS); p->fwd = target->fwd; p->back = target; target->fwd = p->fwd->back = p; ip->oper1->u.offset->v.l = nextlabel++; }}static CODE *code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ CODE *ip; ip = (CODE *) xalloc (sizeof (CODE)); ip->opcode = op; ip->length = len; ip->oper1 = ap1; ip->oper2 = ap2; return ip;}/* * generate a code sequence into the peep list. */void g_code P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ add_peep (code (op, len, ap1, ap2));}#ifdef FLOAT_IEEE/* * generate a floating point code sequence into the peep list. */void g_fcode P4 (OPCODE, op, ILEN, len, ADDRESS *, ap1, ADDRESS *, ap2){ if (len) { len++; } g_code (op, len, ap1, ap2);}#endif /* FLOAT_IEEE *//* * add the instruction pointed to by new to the peep list. */static void add_peep P1 (CODE *, ip){ static CODE *peep_tail; if (peep_head == NIL_CODE) { peep_head = peep_tail = ip; ip->fwd = NIL_CODE; ip->back = NIL_CODE; } else { ip->fwd = NIL_CODE; ip->back = peep_tail; peep_tail->fwd = ip; peep_tail = ip; }}/* * output all code and labels in the peep list. */void flush_peep P1 (unsigned, level){ register CODE *ip; SWITCH *sw; EXPR *ep; LABEL i; /* * perform peephole optimizations */ opt3 (level); /* * generate assembler output */ for (ip = peep_head; ip != NIL_CODE; ip = ip->fwd) { if (ip->opcode == op_label) { put_label (ip->oper1->u.offset->v.l); } else { put_code (ip); } } peep_head = NIL_CODE; ep = mk_lcon (UNDEF_LABEL); for (sw = swtables; sw; sw = sw->next) { put_kseg (alignment_of_type (tp_pointer)); put_label (sw->tablab); for (i = 0; i < sw->numlabs; i++) { ep->v.l = sw->labels[i]; put_pointer (ep); } } swtables = NIL_SWITCH;}/* * delete an instruction referenced by ip */static void peep_delete P1 (CODE *, ip){ if (ip == NIL_CODE) { FATAL ((__FILE__, "peep_delete", "")); } if (ip->back == NIL_CODE) { peep_head = ip->fwd; if (ip->fwd) { ip->fwd->back = NIL_CODE; } next_ip = ip->fwd; } else { if ((ip->back->fwd = ip->fwd) != NIL_CODE) { ip->fwd->back = ip->back; } next_ip = ip->back; } changes++;}/* * deletes lea (Rn),Rn */static void peep_lea P1 (CODE *, ip){ if (ip->oper1->mode == am_ind && ip->oper1->preg == ip->oper2->preg) { peep_delete (ip); return; }}/* * optimizes and instructions */static void peep_and P1 (CODE *, ip){ CODE *prev; IVAL val; if ((ip->oper1->mode != am_immed) || (ip->oper1->u.offset->nodetype != en_icon)) { return; } val = ip->oper1->u.offset->v.i; if (val == -1L) { /* * AND #-1, <ea> * * only sets flags, which the code generator does not know */ peep_delete (ip); return; } prev = ip->back; if (prev == NIL_CODE) { return; } if ((prev->opcode == op_and) && (prev->oper1->mode == am_immed) && is_icon (prev->oper1->u.offset) && is_equal_address (ip->oper2, prev->oper2)) { /* * AND #M, <ea> => AND #(M&N), <ea> * AND #N, <ea> */ prev->oper1->u.offset->v.i &= val; if (prev->length < ip->length) { prev->length = ip->length; } peep_delete (ip); return; }}static void peep_test P1 (CODE *, ip){ CODE *prev = ip->back; if (prev == NULL) { return; } if (!is_equal_address (ip->oper1, ip->oper2)) { return; } /* instruction is just setting the flags */ switch (prev->opcode) { case op_add: case op_sub: case op_and: case op_or: if (is_equal_address (ip->oper2, prev->oper2)) { peep_delete (ip); } break; default: break; }}static void peep_mov P1 (CODE *, ip){ CODE *prev, *next; BOOL memory, altered; if (is_equal_address (ip->oper1, ip->oper2)) { /* * delete mov src,src */ peep_delete (ip); return; } memory = FALSE; switch (ip->oper1->mode) { case am_ind: case am_indx: memory = TRUE; if (ip->oper2->mode != am_dreg && ip->oper2->mode != am_areg) { break; } if (ip->oper1->preg == ip->oper2->preg) { break; } /*FALLTHRU */ case am_dreg: case am_areg: /* * eliminate redundant moves into a register when intervening * instructions only involve registers which cannot affect * the register. */ if (ip->oper2->mode != am_dreg && ip->oper2->mode != am_areg) { break; } for (next = ip->fwd; next != NIL_CODE; next = next->fwd) { switch (next->opcode) { case op_label: case op_bra: case op_call: case op_jmp: case op_ret: case op_leave: return; default: break; } if (is_same_instruction (ip, next)) { peep_delete (next); return; } altered = (BOOL) (op_flags[next->opcode] & DEST_ALTERED); if (next->oper2) { /* two operand instruction */ if (altered && is_equal_oper (ip->oper1, next->oper2)) { return; } switch (next->oper2->mode) { case am_dreg: case am_areg: if (altered && ((ip->oper2->preg == next->oper2->preg) || (ip->oper1->preg == next->oper2->preg))) return; break; case am_ind: case am_indx: if (altered && memory) { return; } break; default: break; } } if (next->oper1) { switch (next->oper1->mode) { case am_dreg: case am_areg: if (next->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && ((ip->oper2->preg == next->oper1->preg) || (ip->oper1->preg == next->oper1->preg))) return; break; case am_ind: case am_indx: if (next->oper2 != NIL_ADDRESS) { break; } /* one operand instruction */ if (altered && memory) { return; } break; default: break; } } } break; case am_immed: if ((ip->oper2->mode == am_dreg || ip->oper2->mode == am_areg) && is_icon (ip->oper1->u.offset) && ip->oper1->u.offset->v.i == 0L) { /* * change mov #0, reg => xor reg, reg */ ip->oper1 = ip->oper2; ip->opcode = op_xor; return; } break; default: if ((prev = ip->back) == NIL_CODE) { return; } /* * think about * * movl (%eax),eax I will make is_equal_address very restrictive! * movl eax,(%eax) * */ if (prev->opcode == op_mov && prev->length == ip->length && is_equal_address (prev->oper1, ip->oper2) && is_equal_address (prev->oper2, ip->oper1)) { /* * change mov src,dest => mov src, dest * mov dest,src */ peep_delete (ip); return; } }}/* * changes cmp $0,reg to test reg,reg if followed by je, jne, jg, jge, jl, jle */static void peep_cmp P1 (CODE *, ip){ CODE *next; if (ip->oper1->mode == am_immed && is_icon (ip->oper1->u.offset) && ip->oper1->u.offset->v.i == 0L && (ip->oper2->mode == am_dreg || ip->oper2->mode == am_areg) && (next = ip->fwd) != NIL_CODE) { switch (next->opcode) { case op_je: case op_jne: case op_jg: case op_jge: case op_jl: case op_jle: ip->opcode = op_test; ip->oper1 = ip->oper2; break; default: break; } }}/* * changes things like * * movw src,%ax * movzwl %ax,%eax * * to * * movzwl src,%eax * * DO NOT DESTRUCT * movw %di,%ax
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -