Skip to content

Commit

Permalink
Start splitting SSA versions at guards
Browse files Browse the repository at this point in the history
We have so far used a single SSA version to represent both pre-guard
data and post-guard data. Initially, guards were only ever inserted
after the read of a value, so this wasn't a big problem. However:

* Now we insert extra guards during spesh plugin optimization and
  when doing some speculative call optimizations. There may be
  read instructions between the initial write and the place that we
  insert the guard, thus we cannot safely attach the facts the guard
  asserts to the SSA version as they aren't the case pre-guard.
* This in turn leads to duplicate guards being inserted on the same
  data in various cases, and other missed lowering opportunities.
* Inlining may let us prove that a guard on a return value will
  always be true and thus allow us to eliminate the guard. However,
  since we don't have a before/after at the guard point, we cannot
  do that.

This commit takes a first step to switching guards to take in one
version and produce another version, so we can deal with facts both
before and after the guard. The spesh plugin case and speculative
call argument case are not yet updated, and so temporarily disabled
until they are; other than that, this seems to work well.
  • Loading branch information
jnthn committed Aug 10, 2018
1 parent 4fc267b commit 5bcae47
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 125 deletions.
135 changes: 71 additions & 64 deletions lib/MAST/Ops.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -811,82 +811,82 @@ BEGIN {
2028,
2030,
2032,
2035,
2038,
2041,
2036,
2040,
2044,
2047,
2050,
2053,
2055,
2057,
2054,
2058,
2061,
2063,
2065,
2067,
2069,
2071,
2073,
2075,
2077,
2079,
2081,
2064,
2068,
2070,
2072,
2074,
2076,
2078,
2080,
2082,
2084,
2087,
2090,
2093,
2086,
2088,
2091,
2094,
2097,
2098,
2100,
2104,
2105,
2107,
2110,
2113,
2116,
2119,
2122,
2125,
2128,
2131,
2134,
2137,
2140,
2143,
2146,
2149,
2152,
2111,
2114,
2117,
2120,
2123,
2126,
2129,
2132,
2135,
2138,
2141,
2144,
2147,
2150,
2153,
2156,
2160,
2159,
2163,
2166,
2169,
2172,
2175,
2178,
2181,
2184,
2187,
2190,
2193,
2167,
2170,
2173,
2176,
2179,
2182,
2185,
2188,
2191,
2194,
2197,
2201,
2200,
2204,
2207,
2208,
2210,
2212,
2211,
2214,
2218,
2220,
2222,
2222,
2222,
2223,
2224,
2224,
2215,
2217,
2219,
2221,
2225,
2227,
2231);
2229,
2229,
2229,
2230,
2231,
2231,
2232,
2234,
2238);
MAST::Ops.WHO<@counts> := nqp::list_i(0,
2,
2,
Expand Down Expand Up @@ -1694,15 +1694,15 @@ BEGIN {
3,
2,
2,
4,
4,
4,
3,
3,
4,
4,
3,
3,
3,
3,
3,
2,
2,
4,
2,
2,
Expand Down Expand Up @@ -3803,12 +3803,15 @@ BEGIN {
161,
65,
65,
66,
65,
128,
152,
66,
65,
128,
152,
66,
65,
128,
152,
Expand All @@ -3818,14 +3821,18 @@ BEGIN {
65,
128,
152,
66,
65,
128,
152,
66,
65,
128,
152,
66,
65,
152,
66,
65,
152,
66,
Expand Down
45 changes: 26 additions & 19 deletions src/core/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -5340,28 +5340,31 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
cur_op += 4;
goto NEXT;
OP(sp_guard): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMObject *check = GET_REG(cur_op, 2).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 8;
->effective_spesh_slots[GET_UI16(cur_op, 4)];
GET_REG(cur_op, 0).o = check;
cur_op += 10;
if (!check || STABLE(check) != want)
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardconc): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMObject *check = GET_REG(cur_op, 2).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 8;
->effective_spesh_slots[GET_UI16(cur_op, 4)];
GET_REG(cur_op, 0).o = check;
cur_op += 10;
if (!check || !IS_CONCRETE(check) || STABLE(check) != want)
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardtype): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMObject *check = GET_REG(cur_op, 2).o;
MVMSTable *want = (MVMSTable *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 8;
->effective_spesh_slots[GET_UI16(cur_op, 4)];
GET_REG(cur_op, 0).o = check;
cur_op += 10;
if (!check || IS_CONCRETE(check) || STABLE(check) != want)
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
Expand All @@ -5388,33 +5391,37 @@ void MVM_interp_run(MVMThreadContext *tc, void (*initial_invoke)(MVMThreadContex
goto NEXT;
}
OP(sp_guardobj): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMObject *check = GET_REG(cur_op, 2).o;
MVMObject *want = (MVMObject *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 8;
->effective_spesh_slots[GET_UI16(cur_op, 4)];
GET_REG(cur_op, 0).o = check;
cur_op += 10;
if (check != want)
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardnotobj): {
MVMObject *check = GET_REG(cur_op, 0).o;
MVMObject *check = GET_REG(cur_op, 2).o;
MVMObject *do_not_want = (MVMObject *)tc->cur_frame
->effective_spesh_slots[GET_UI16(cur_op, 2)];
cur_op += 8;
->effective_spesh_slots[GET_UI16(cur_op, 4)];
GET_REG(cur_op, 0).o = check;
cur_op += 10;
if (check == do_not_want)
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardjustconc): {
MVMObject *check = GET_REG(cur_op, 0).o;
cur_op += 6;
MVMObject *check = GET_REG(cur_op, 2).o;
GET_REG(cur_op, 0).o = check;
cur_op += 8;
if (!IS_CONCRETE(check))
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
}
OP(sp_guardjusttype): {
MVMObject *check = GET_REG(cur_op, 0).o;
cur_op += 6;
MVMObject *check = GET_REG(cur_op, 2).o;
GET_REG(cur_op, 0).o = check;
cur_op += 8;
if (IS_CONCRETE(check))
MVM_spesh_deopt_one(tc, GET_UI32(cur_op, -4));
goto NEXT;
Expand Down
14 changes: 7 additions & 7 deletions src/core/oplist
Original file line number Diff line number Diff line change
Expand Up @@ -875,9 +875,9 @@ speshguardnotobj r(obj) r(obj)
# guard = guard on type only; index is spesh slot with type
# guardconc = guard on type + concrete; index is spesh slot with type
# guardtype = guard on type + type object; index is spesh slot with type
sp_guard .s r(obj) sslot uint32 :maycausedeopt
sp_guardconc .s r(obj) sslot uint32 :maycausedeopt
sp_guardtype .s r(obj) sslot uint32 :maycausedeopt
sp_guard .s w(obj) r(obj) sslot uint32 :maycausedeopt
sp_guardconc .s w(obj) r(obj) sslot uint32 :maycausedeopt
sp_guardtype .s w(obj) r(obj) sslot uint32 :maycausedeopt

# Code guard operations. Trigger de-optimization if the guard is violated.
# guardsf = guard on being an MVMCode with specified static frame inside
Expand All @@ -887,12 +887,12 @@ sp_guardsf .s r(obj) sslot uint32 :maycausedeopt
sp_guardsfouter .s r(obj) sslot uint32 :maycausedeopt

# Literal object match and non-match guards.
sp_guardobj .s r(obj) sslot uint32 :maycausedeopt
sp_guardnotobj .s r(obj) sslot uint32 :maycausedeopt
sp_guardobj .s w(obj) r(obj) sslot uint32 :maycausedeopt
sp_guardnotobj .s w(obj) r(obj) sslot uint32 :maycausedeopt

# Guards that check concrete or type object, without caring for type.
sp_guardjustconc .s r(obj) uint32 :maycausedeopt
sp_guardjusttype .s r(obj) uint32 :maycausedeopt
sp_guardjustconc .s w(obj) r(obj) uint32 :maycausedeopt
sp_guardjusttype .s w(obj) r(obj) uint32 :maycausedeopt

# Specialized form of rebless that will always do a deopt one out of the
# current code as well as a deopt all.
Expand Down
Loading

0 comments on commit 5bcae47

Please sign in to comment.