summaryrefslogtreecommitdiff
path: root/lcode.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-12 11:38:42 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-07-12 11:38:42 -0300
commitf6aab3ec1f111cd8d968bdcb7ca800e93b819d24 (patch)
tree4c36c418ecc9062e6d95de73457198b38b0afce9 /lcode.c
parentbe8445d7e4b6122620c428877b51a27d464253d5 (diff)
downloadlua-github-f6aab3ec1f111cd8d968bdcb7ca800e93b819d24.tar.gz
First implementation of constant propagation
Local constant variables initialized with compile-time constants are optimized away from the code.
Diffstat (limited to 'lcode.c')
-rw-r--r--lcode.c56
1 files changed, 55 insertions, 1 deletions
diff --git a/lcode.c b/lcode.c
index 837253f4..74ff47de 100644
--- a/lcode.c
+++ b/lcode.c
@@ -68,6 +68,30 @@ static int tonumeral (const expdesc *e, TValue *v) {
/*
+** If expression is a constant, fills 'v' with its value
+** and returns 1. Otherwise, returns 0.
+*/
+int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v) {
+ if (hasjumps(e))
+ return 0; /* not a constant */
+ switch (e->k) {
+ case VFALSE: case VTRUE:
+ setbvalue(v, e->k == VTRUE);
+ return 1;
+ case VNIL:
+ setnilvalue(v);
+ return 1;
+ case VK: {
+ TValue *k = &fs->f->k[e->u.info];
+ setobj(fs->ls->L, v, k);
+ return 1;
+ }
+ default: return tonumeral(e, v);
+ }
+}
+
+
+/*
** Return the previous instruction of the current code. If there
** may be a jump target between the current instruction and the
** previous one, return an invalid instruction (to avoid wrong
@@ -630,6 +654,31 @@ static void luaK_float (FuncState *fs, int reg, lua_Number f) {
/*
+** Convert a constant in 'v' into an expression description 'e'
+*/
+static void const2exp (FuncState *fs, TValue *v, expdesc *e) {
+ switch (ttypetag(v)) {
+ case LUA_TNUMINT:
+ e->k = VKINT; e->u.ival = ivalue(v);
+ break;
+ case LUA_TNUMFLT:
+ e->k = VKFLT; e->u.nval = fltvalue(v);
+ break;
+ case LUA_TBOOLEAN:
+ e->k = bvalue(v) ? VTRUE : VFALSE;
+ break;
+ case LUA_TNIL:
+ e->k = VNIL;
+ break;
+ case LUA_TSHRSTR: case LUA_TLNGSTR:
+ e->k = VK; e->u.info = luaK_stringK(fs, tsvalue(v));
+ break;
+ default: lua_assert(0);
+ }
+}
+
+
+/*
** Fix an expression to return the number of results 'nresults'.
** Either 'e' is a multi-ret expression (function call or vararg)
** or 'nresults' is LUA_MULTRET (as any expression can satisfy that).
@@ -677,6 +726,11 @@ void luaK_setoneret (FuncState *fs, expdesc *e) {
*/
void luaK_dischargevars (FuncState *fs, expdesc *e) {
switch (e->k) {
+ case VCONST: {
+ TValue *val = &fs->ls->dyd->actvar.arr[e->u.info].k;
+ const2exp(fs, val, e);
+ break;
+ }
case VLOCAL: { /* already in a register */
e->u.info = e->u.var.sidx;
e->k = VNONRELOC; /* becomes a non-relocatable value */
@@ -1074,7 +1128,6 @@ void luaK_goiffalse (FuncState *fs, expdesc *e) {
** Code 'not e', doing constant folding.
*/
static void codenot (FuncState *fs, expdesc *e) {
- luaK_dischargevars(fs, e);
switch (e->k) {
case VNIL: case VFALSE: {
e->k = VTRUE; /* true == not nil == not false */
@@ -1447,6 +1500,7 @@ static void codeeq (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) {
*/
void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP};
+ luaK_dischargevars(fs, e);
switch (op) {
case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */
if (constfolding(fs, op + LUA_OPUNM, e, &ef))