X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fgit%2Fpeephole.c;fp=interpreters%2Fgit%2Fpeephole.c;h=4068b6796a0ba4e5c0235aad14174805d1f69a5d;hb=147a8cbf17f2b3379277bf7d37cda9866510f16c;hp=0000000000000000000000000000000000000000;hpb=7de488aa6a1709a4d5c59b5ff59862105c1748c5;p=rodin%2Fchimara.git diff --git a/interpreters/git/peephole.c b/interpreters/git/peephole.c new file mode 100644 index 0000000..4068b67 --- /dev/null +++ b/interpreters/git/peephole.c @@ -0,0 +1,131 @@ +// $Id: peephole.c,v 1.6 2003/10/13 22:53:04 iain Exp $ +// Peephole optimiser for git + +#include "git.h" + +static Label sLastOp; + +extern void resetPeepholeOptimiser () +{ + sLastOp = label_nop; +} + +#define REPLACE_SINGLE(lastOp,thisOp,newOp) \ + case label_ ## thisOp: \ + if (sLastOp == label_ ## lastOp) \ + { \ + op = label_ ## newOp; \ + goto replaceNoOperands; \ + } \ + break + +#define CASE_NO_OPERANDS(lastOp,newOp) \ + case label_ ## lastOp: op = label_ ## newOp; goto replaceNoOperands + +#define CASE_ONE_OPERAND(lastOp,newOp) \ + case label_ ## lastOp: op = label_ ## newOp; goto replaceOneOperand + +#define REPLACE_STORE(storeOp) \ + case label_ ## storeOp: \ + switch(sLastOp) \ + { \ + CASE_NO_OPERANDS (add_discard, add_ ## storeOp); \ + CASE_NO_OPERANDS (sub_discard, sub_ ## storeOp); \ + CASE_NO_OPERANDS (mul_discard, mul_ ## storeOp); \ + CASE_NO_OPERANDS (div_discard, div_ ## storeOp); \ + CASE_NO_OPERANDS (mod_discard, mod_ ## storeOp); \ + CASE_NO_OPERANDS (neg_discard, neg_ ## storeOp); \ + CASE_NO_OPERANDS (bitand_discard, bitand_ ## storeOp); \ + CASE_NO_OPERANDS (bitor_discard, bitor_ ## storeOp); \ + CASE_NO_OPERANDS (bitxor_discard, bitxor_ ## storeOp); \ + CASE_NO_OPERANDS (bitnot_discard, bitnot_ ## storeOp); \ + CASE_NO_OPERANDS (shiftl_discard, shiftl_ ## storeOp); \ + CASE_NO_OPERANDS (sshiftr_discard, sshiftr_ ## storeOp); \ + CASE_NO_OPERANDS (ushiftr_discard, ushiftr_ ## storeOp); \ + CASE_NO_OPERANDS (copys_discard, copys_ ## storeOp); \ + CASE_NO_OPERANDS (copyb_discard, copyb_ ## storeOp); \ + CASE_NO_OPERANDS (sexs_discard, sexs_ ## storeOp); \ + CASE_NO_OPERANDS (sexb_discard, sexb_ ## storeOp); \ + CASE_NO_OPERANDS (aload_discard, aload_ ## storeOp); \ + CASE_NO_OPERANDS (aloads_discard, aloads_ ## storeOp); \ + CASE_NO_OPERANDS (aloadb_discard, aloadb_ ## storeOp); \ + CASE_NO_OPERANDS (aloadbit_discard, aloadbit_ ## storeOp); \ + default: break; \ + } \ + break + +#define REPLACE_L1_L2(mode2) \ + case label_L2_ ## mode2: \ + switch(sLastOp) \ + { \ + CASE_ONE_OPERAND (L1_const, L1_const_L2_ ## mode2); \ + CASE_NO_OPERANDS (L1_stack, L1_stack_L2_ ## mode2); \ + CASE_ONE_OPERAND (L1_local, L1_local_L2_ ## mode2); \ + CASE_ONE_OPERAND (L1_addr, L1_addr_L2_ ## mode2); \ + default: break; \ + } \ + break + +#define REPLACE_LOAD_OP(loadOp,reg) \ + case label_ ## loadOp: \ + switch(sLastOp) \ + { \ + CASE_ONE_OPERAND (reg ## _const, loadOp ## _ ## reg ## _const); \ + CASE_NO_OPERANDS (reg ## _stack, loadOp ## _ ## reg ## _stack); \ + CASE_ONE_OPERAND (reg ## _local, loadOp ## _ ## reg ## _local); \ + CASE_ONE_OPERAND (reg ## _addr, loadOp ## _ ## reg ## _addr); \ + default: break; \ + } \ + break + +extern void emitCode (Label op) +{ + git_uint32 temp; + + if (gPeephole) + { + switch (op) + { + REPLACE_SINGLE (args_stack, call_stub_discard, args_stack_call_stub_discard); + REPLACE_SINGLE (args_stack, call_stub_addr, args_stack_call_stub_addr); + REPLACE_SINGLE (args_stack, call_stub_local, args_stack_call_stub_local); + REPLACE_SINGLE (args_stack, call_stub_stack, args_stack_call_stub_stack); + + REPLACE_STORE (S1_stack); + REPLACE_STORE (S1_local); + REPLACE_STORE (S1_addr); + + REPLACE_L1_L2 (const); + REPLACE_L1_L2 (stack); + REPLACE_L1_L2 (local); + REPLACE_L1_L2 (addr); + + REPLACE_LOAD_OP (return, L1); + REPLACE_LOAD_OP (astore, L3); + REPLACE_LOAD_OP (astores, L3); + REPLACE_LOAD_OP (astoreb, L3); + REPLACE_LOAD_OP (astorebit, L3); + + default: break; + } + } + goto noPeephole; + +replaceOneOperand: + // The previous opcode has one operand, so + // we have to go back two steps to update it. + temp = undoEmit(); // Save the operand. + undoEmit(); // Remove the old opcode. + emitFinalCode (op); // Emit the new opcode. + emitData (temp); // Emit the operand again. + goto done; + +replaceNoOperands: + undoEmit(); + // ... fall through +noPeephole: + emitFinalCode (op); + // ... fall through +done: + sLastOp = op; +}