Make sure x86 ATOMIC_CAS doesn't overwrite its own operands.
[mono-debugger.git] / mono / mini / cprop.c
blobe1ad2d712d25169357298d579681ba04a7e82bd7
1 /*
2 * cprop.c: Constant propagation.
4 * Author:
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2003 Ximian, Inc.
8 */
10 /* dumb list-based implementation for now */
12 typedef struct _MiniACP MiniACP;
14 struct _MiniACP {
15 MiniACP *next;
16 short dreg;
17 short sreg;
18 int type;
21 static int
22 copy_value (MiniACP *acp, int reg, int type)
24 MiniACP *tmp = acp;
26 //g_print ("search reg %d '%c'\n", reg, type);
27 while (tmp) {
28 // g_print ("considering dreg %d, sreg %d '%c'\n", tmp->dreg, tmp->sreg, tmp->type);
29 if (tmp->type == type && tmp->dreg == reg) {
30 // g_print ("copy prop from %d to %d\n", tmp->sreg, tmp->dreg);
31 return tmp->sreg;
33 tmp = tmp->next;
35 return reg;
38 static MiniACP*
39 remove_acp (MiniACP *acp, int reg, int type)
41 MiniACP *tmp = acp;
42 MiniACP *prev = NULL;
44 while (tmp) {
45 if (tmp->type == type && (tmp->dreg == reg || tmp->sreg == reg)) {
46 if (prev)
47 prev->next = tmp->next;
48 else
49 acp = tmp->next;
50 } else {
51 prev = tmp;
53 tmp = tmp->next;
55 return acp;
58 static MiniACP*
59 add_acp (MonoCompile *cfg, MiniACP *acp, int sreg, int dreg, int type)
61 MiniACP *newacp = mono_mempool_alloc (cfg->mempool, sizeof (MiniACP));;
62 newacp->type = type;
63 newacp->sreg = sreg;
64 newacp->dreg = dreg;
66 newacp->next = acp;
67 return newacp;
70 static void
71 local_copy_prop (MonoCompile *cfg, MonoInst *code)
73 MiniACP *acp = NULL;
74 const char *spec;
75 MonoInst *ins = code;
77 //g_print ("starting BB\n");
79 while (ins) {
80 spec = ins_get_spec (ins->opcode);
81 //print_ins (0, ins);
83 if (spec [MONO_INST_CLOB] != 's' && spec [MONO_INST_CLOB] != '1' && spec [MONO_INST_CLOB] != 'd' && spec [MONO_INST_CLOB] != 'a' && spec [MONO_INST_CLOB] != 'c') {
84 if (spec [MONO_INST_SRC1] == 'f') {
85 ins->sreg1 = copy_value (acp, ins->sreg1, 'f');
86 } else if (spec [MONO_INST_SRC1]) {
87 ins->sreg1 = copy_value (acp, ins->sreg1, 'i');
91 if (spec [MONO_INST_CLOB] != 's') {
92 if (spec [MONO_INST_SRC2] == 'f') {
93 ins->sreg2 = copy_value (acp, ins->sreg2, 'f');
94 } else if (spec [MONO_INST_SRC2]) {
95 ins->sreg2 = copy_value (acp, ins->sreg2, 'i');
99 /* invalidate pairs */
100 if (spec [MONO_INST_DEST] == 'f') {
101 acp = remove_acp (acp, ins->dreg, 'f');
102 } else if (spec [MONO_INST_DEST]) {
103 acp = remove_acp (acp, ins->dreg, 'i');
106 /* insert pairs */
108 * Later copy-propagate also immediate values and memory stores.
110 if (ins->opcode == OP_MOVE && ins->sreg1 != ins->dreg) {
111 // g_print ("added acp of %d <- %d '%c'\n", ins->dreg, ins->sreg1, spec [MONO_INST_SRC1]);
112 acp = add_acp (cfg, acp, ins->sreg1, ins->dreg, spec [MONO_INST_SRC1]);
115 if (spec [MONO_INST_CLOB] == 'c') {
116 /* this is a call, invalidate all the pairs */
117 acp = NULL;
118 } else if ((ins->opcode) == OP_BR || (ins->opcode >= CEE_BEQ && ins->opcode <= CEE_BLT) ||
119 (ins->opcode >= CEE_BNE_UN && ins->opcode <= CEE_BLT_UN)) {
120 acp = NULL; /* invalidate all pairs */
121 /* it's not enough to invalidate the pairs, because we don't always
122 * generate extended basic blocks (the BRANCH_LABEL stuff in the burg rules)
123 * This issue is going to reduce a lot the possibilities for optimization!
125 return;
127 ins = ins->next;