aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_opt_loop.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/src/lj_opt_loop.c b/src/lj_opt_loop.c
index c3d115b2..460297b6 100644
--- a/src/lj_opt_loop.c
+++ b/src/lj_opt_loop.c
@@ -104,7 +104,7 @@
104static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi, 104static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi,
105 SnapNo onsnap) 105 SnapNo onsnap)
106{ 106{
107 int pass2 = 0; 107 int passx = 0;
108 IRRef i, nslots; 108 IRRef i, nslots;
109 IRRef invar = J->chain[IR_LOOP]; 109 IRRef invar = J->chain[IR_LOOP];
110 /* Pass #1: mark redundant and potentially redundant PHIs. */ 110 /* Pass #1: mark redundant and potentially redundant PHIs. */
@@ -116,16 +116,28 @@ static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi,
116 } else if (!(IR(rref)->op1 == lref || IR(rref)->op2 == lref)) { 116 } else if (!(IR(rref)->op1 == lref || IR(rref)->op2 == lref)) {
117 /* Quick check for simple recurrences failed, need pass2. */ 117 /* Quick check for simple recurrences failed, need pass2. */
118 irt_setmark(IR(lref)->t); 118 irt_setmark(IR(lref)->t);
119 pass2 = 1; 119 passx = 1;
120 } 120 }
121 } 121 }
122 /* Pass #2: traverse variant part and clear marks of non-redundant PHIs. */ 122 /* Pass #2: traverse variant part and clear marks of non-redundant PHIs. */
123 if (pass2) { 123 if (passx) {
124 SnapNo s; 124 SnapNo s;
125 for (i = J->cur.nins-1; i > invar; i--) { 125 for (i = J->cur.nins-1; i > invar; i--) {
126 IRIns *ir = IR(i); 126 IRIns *ir = IR(i);
127 if (!irref_isk(ir->op1)) irt_clearmark(IR(ir->op1)->t);
128 if (!irref_isk(ir->op2)) irt_clearmark(IR(ir->op2)->t); 127 if (!irref_isk(ir->op2)) irt_clearmark(IR(ir->op2)->t);
128 if (!irref_isk(ir->op1)) {
129 irt_clearmark(IR(ir->op1)->t);
130 if (ir->op1 < invar &&
131 ir->o >= IR_CALLN && ir->o <= IR_CARG) { /* ORDER IR */
132 ir = IR(ir->op1);
133 while (ir->o == IR_CARG) {
134 if (!irref_isk(ir->op2)) irt_clearmark(IR(ir->op2)->t);
135 if (irref_isk(ir->op1)) break;
136 ir = IR(ir->op1);
137 irt_clearmark(ir->t);
138 }
139 }
140 }
129 } 141 }
130 for (s = J->cur.nsnap-1; s >= onsnap; s--) { 142 for (s = J->cur.nsnap-1; s >= onsnap; s--) {
131 SnapShot *snap = &J->cur.snap[s]; 143 SnapShot *snap = &J->cur.snap[s];
@@ -155,19 +167,35 @@ static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi,
155 break; 167 break;
156 } 168 }
157 } 169 }
158 /* Pass #4: emit PHI instructions or eliminate PHIs. */ 170 /* Pass #4: propagate non-redundant PHIs. */
171 while (passx) {
172 passx = 0;
173 for (i = 0; i < nphi; i++) {
174 IRRef lref = phi[i];
175 IRIns *ir = IR(lref);
176 if (!irt_ismarked(ir->t)) { /* Propagate only from unmarked PHIs. */
177 IRRef rref = subst[lref];
178 if (lref == rref) { /* Mark redundant PHI. */
179 irt_setmark(ir->t);
180 } else {
181 IRIns *irr = IR(rref);
182 if (irt_ismarked(irr->t)) { /* Right ref points to other PHI? */
183 irt_clearmark(irr->t); /* Mark that PHI as non-redundant. */
184 passx = 1; /* Retry. */
185 }
186 }
187 }
188 }
189 }
190 /* Pass #5: emit PHI instructions or eliminate PHIs. */
159 for (i = 0; i < nphi; i++) { 191 for (i = 0; i < nphi; i++) {
160 IRRef lref = phi[i]; 192 IRRef lref = phi[i];
161 IRIns *ir = IR(lref); 193 IRIns *ir = IR(lref);
162 if (!irt_ismarked(ir->t)) { /* Emit PHI if not marked and not redundant. */ 194 if (!irt_ismarked(ir->t)) { /* Emit PHI if not marked. */
163 IRRef rref = subst[lref]; 195 IRRef rref = subst[lref];
164 if (lref == rref) { 196 if (rref > invar)
165 irt_clearphi(ir->t); 197 irt_setphi(IR(rref)->t);
166 } else { 198 emitir_raw(IRT(IR_PHI, irt_type(ir->t)), lref, rref);
167 if (rref > invar)
168 irt_setphi(IR(rref)->t);
169 emitir_raw(IRT(IR_PHI, irt_type(ir->t)), lref, rref);
170 }
171 } else { /* Otherwise eliminate PHI. */ 199 } else { /* Otherwise eliminate PHI. */
172 irt_clearmark(ir->t); 200 irt_clearmark(ir->t);
173 irt_clearphi(ir->t); 201 irt_clearphi(ir->t);