📄 peepx86.c
字号:
* movzbl %al,%eax * since %di,%si have no byte-components. */static void peep_xtend P1 (CODE *, ip){ CODE *prev = ip->back; ILEN size; if (prev != NIL_CODE && prev->opcode == op_mov && is_equal_address (prev->oper2, ip->oper1) && is_equal_address (ip->oper1, ip->oper2)) { if ((prev->oper1->mode == am_dreg || prev->oper1->mode == am_areg) && (prev->oper1->preg == ESI || prev->oper1->preg == EDI)) return; ip->oper1 = prev->oper1; peep_delete (prev); } /* * the code generator, or this procedure, may generate code like * * movsbl $const, %reg * * this is not a legal instruction. * we will change it to a mov instruction here */ if (ip->oper1->mode != am_immed) { return; } if (ip->opcode == op_movsbw || ip->opcode == op_movzbw) { size = IL2; } else { size = IL4; } ip->length = size; ip->opcode = op_mov;}/* * changes: * add #1 => inc * add #-1 => dec * sub #1 => dec * sub #-1 => inc */static void peep_addsub P2 (CODE *, ip, IVAL, flag){ if (ip->oper1->mode != am_immed || ip->oper1->u.offset->nodetype != en_icon) { return; } if (ip->oper2->preg == STACKPTR && is_dest_overwritten (ip->oper2, ip)) { peep_delete (ip); return; } if (ip->fwd && (ip->fwd->opcode == op_adc || ip->fwd->opcode == op_sbb)) { return; } flag *= ip->oper1->u.offset->v.i; switch (flag) { case 1l: ip->opcode = op_inc; ip->oper1 = ip->oper2; ip->oper2 = NIL_ADDRESS; break; case -1l: ip->opcode = op_dec; ip->oper1 = ip->oper2; ip->oper2 = NIL_ADDRESS; break; case -2l: if (ip->length == IL2 && (ip->oper2->mode == am_dreg || ip->oper2->mode == am_areg) && ip->oper2->preg == ESP) { ip->opcode = op_push; ip->oper1 = mk_reg (ECX); ip->oper2 = NIL_ADDRESS; } break; case -4l: if (ip->length == IL4 && (ip->oper2->mode == am_dreg || ip->oper2->mode == am_areg) && ip->oper2->preg == ESP) { ip->opcode = op_push; ip->oper1 = mk_reg (ECX); ip->oper2 = NIL_ADDRESS; } break; default: break; }}/* * peephole optimization for unconditional transfers. deletes instructions * which have no path. applies to bra, jmp, and rts instructions. */static void peep_uctran P1 (CODE *, ip){ while (ip->fwd != NIL_CODE && ip->fwd->opcode != op_label) peep_delete (ip->fwd);}/* * optimizes conditional branch over a bra. */static void peep_bxx P1 (CODE *, ip){ static OPCODE revcond[] = { op_jne, op_je, op_jge, op_jg, op_jle, op_jl, op_jbe, op_jb, op_jae, op_ja }; CODE *next = ip->fwd; if (next == NIL_CODE) { return; } if (next->opcode == op_bra) { /* peep_uctran increases the 'hit' probability */ peep_uctran (next); next = next->fwd; if (next == NIL_CODE) { return; } if (next->opcode == op_label && ip->oper1->u.offset->v.l == next->oper1->u.offset->v.l) { ip->fwd->opcode = revcond[(int) ip->opcode - (int) op_je]; peep_delete (ip); } }}/* * if a label is followed by a branch to another label, the * branch statement can be deleted when the label is moved */static void peep_label P1 (CODE *, ip){ CODE *prev, *next, *target; SWITCH *sw; LABEL i, lab, label; if ((next = ip->fwd) == NIL_CODE) { return; } if (!optimize_option) { return; } lab = ip->oper1->u.offset->v.l; switch (next->opcode) { case op_label: /* if a label is followed by a label then common them up */ label = next->oper1->u.offset->v.l; for (target = peep_head; target != NIL_CODE; target = target->fwd) { if (is_label_used (target->oper1, label)) { target->oper1->u.offset->v.l = lab; } if (is_label_used (target->oper2, label)) { target->oper2->u.offset->v.l = lab; } } for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { for (i = (LABEL) 0; i < sw->numlabs; i++) { if (sw->labels[i] == label) { sw->labels[i] = ip->oper1->u.offset->v.l; changes++; } } } peep_delete (next); break; case op_bra: prev = ip->back; /* * To make this fast, assume that the label number is really * next->oper1->u.offset->v.l */ label = next->oper1->u.offset->v.l; if (label == ip->oper1->u.offset->v.l) { return; } target = peep_head; /* * look for the label */ while (target != NIL_CODE) { if (target->opcode == op_label && target->oper1->u.offset->v.l == label) break; target = target->fwd; } /* we should have found it */ if (target == NIL_CODE) { message (MSG_PEEPLABEL); return; } /* move label */ peep_delete (ip); ip->fwd = target->fwd; ip->back = target; target->fwd = ip; if (ip->fwd != NIL_CODE) { ip->fwd->back = ip; } /* possibly remove branches */ /* in fact, prev is always != 0 if peep_delete has succeeded */ if (prev != NIL_CODE) { if (prev->opcode == op_bra || prev->opcode == op_jmp || prev->opcode == op_ret) peep_uctran (prev); } break; default: /* check that there are still references to this label */ label = ip->oper1->u.offset->v.l; for (target = peep_head; target != NIL_CODE; target = target->fwd) { if ((target != ip) && (is_label_used (target->oper1, lab) || is_label_used (target->oper2, lab))) return; } for (sw = swtables; sw != NIL_SWITCH; sw = sw->next) { for (i = 0; i < sw->numlabs; i++) { if (sw->labels[i] == label) { return; } } } peep_delete (ip); break; }}/* delete branches to the following statement */static void peep_bra P1 (CODE *, ip){ CODE *p = ip->fwd; CODE *target; LABEL label = ip->oper1->u.offset->v.l; int count; /* delete branches to the following statement */ while (p != NIL_CODE && p->opcode == op_label) { if (p->oper1->u.offset->v.l == label) { peep_delete (ip); return; } p = p->fwd; } if (!optimize_option) { return; } target = find_label (label); /* we should have found it */ if (target == NIL_CODE) { FATAL ((__FILE__, "peep_bra", "target == 0")); } /* Space optimisation: * if the code before the target of the branch is itself a branch * then we can move the destination block of code to eliminate the * branch */ p = target->back; if (p != NIL_CODE && ((p->opcode == op_bra) || (p->opcode == op_jmp) || (p->opcode == op_ret))) { p = block_end (target); if (p != NIL_CODE && p != ip) { if (ip->fwd) { ip->fwd->back = p; } if (p->fwd) { p->fwd->back = target->back; } target->back->fwd = p->fwd; p->fwd = ip->fwd; target->back = ip; ip->fwd = target; peep_delete (ip); return; } } /* Space optimisation: * if the code before the branch instruction is the same as the * instruction before the label the branch can be moved back an * instruction. */ p = ip->back; previous_instruction (target); if (p == target) { return; } /* now skip back over identical instruction sequences */ while (is_same_instruction (p, target)) { p = p->back; previous_instruction (target); peep_delete (p->fwd); } check_label (ip, target); label = ip->oper1->u.offset->v.l; /* Space optimisation: * Optimise for the situation where two branches to the same * target label have identical instruction sequences * leading up to the branch. We can instead eliminate one * of these instruction sequences by branching to the other one. */ for (target = peep_head; target != NIL_CODE; target = target->fwd) { if ((target != ip) && (target->opcode == op_bra) && (target->oper1->u.offset->v.l == label)) { CODE *t = target; p = ip->back; previous_instruction (t); count = 0; while (is_same_instruction (p, t)) { p = p->back; previous_instruction (t); peep_delete (p->fwd); count++; } if (count != 0) { check_label (ip, t); break; } } } peep_uctran (ip);}/* delete multiple debugging line statements */static void peep_line P1 (CODE *, ip){ CODE *ip2; if (ip->fwd == NIL_CODE) { return; } switch (ip->fwd->opcode) { case op_line: peep_delete (ip); break; case op_label: /* move the line number to after the label */ ip2 = ip->fwd; if (ip->back) { ip->back->fwd = ip2; } else { peep_head = ip2; } if (ip2->fwd) { ip2->fwd->back = ip; } ip2->back = ip->back; ip->fwd = ip2->fwd; ip2->fwd = ip; ip->back = ip2; break; default: break; }}/* * peephole optimizer. This routine calls the instruction specific * optimization routines above for each instruction in the peep list. */static void opt3 P1 (unsigned, level){ CODE *ip; if (level == PEEP_NONE) { return; } do { changes = 0; if (is_peep_phase (level, PEEP_INSTRUCTION)) { /* * Instruction specific optisations */ for (next_ip = peep_head; (ip = next_ip) != NIL_CODE; next_ip = ip->fwd) { switch (ip->opcode) { case op_and: peep_and (ip); break; case op_test: peep_test (ip); break; case op_movzbw: case op_movsbw: case op_movzbl: case op_movsbl: case op_movzwl: case op_movswl: peep_xtend (ip); break; case op_lea: peep_lea (ip); break; case op_mov: peep_mov (ip); break; case op_add: peep_addsub (ip, 1l); break; case op_sub: peep_addsub (ip, -1l); break; case op_cmp: peep_cmp (ip); break; default: break; } } } if (is_peep_phase (level, PEEP_JUMPS)) { /* * Flow control optimisations. */ for (next_ip = peep_head; (ip = next_ip) != NIL_CODE; next_ip = ip->fwd) { switch (ip->opcode) { case op_je: case op_jne: case op_jg: case op_jge: case op_jle: case op_jl: case op_ja: case op_jae: case op_jbe: case op_jb: peep_bxx (ip); break; case op_bra: peep_bra (ip); break; case op_jmp: case op_ret: peep_uctran (ip); break; case op_label: peep_label (ip); break; case op_line: peep_line (ip); break; default: break; } } }#ifdef VERBOSE if (verbose_option && changes) { message (MSG_PEEPCHANGES, changes); }#endif /* VERBOSE */ } while (changes);}#endif /* INTEL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -