1/*
2** Common header for IR emitter and optimizations.
3** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
4*/
5
6#ifndef _LJ_IROPT_H
7#define _LJ_IROPT_H
8
9#include <stdarg.h>
10
11#include "lj_obj.h"
12#include "lj_jit.h"
13
14#if LJ_HASJIT
15/* IR emitter. */
16LJ_FUNC void LJ_FASTCALL lj_ir_growtop(jit_State *J);
17LJ_FUNC TRef LJ_FASTCALL lj_ir_emit(jit_State *J);
18
19/* Save current IR in J->fold.ins, but do not emit it (yet). */
20static LJ_AINLINE void lj_ir_set_(jit_State *J, uint16_t ot, IRRef1 a, IRRef1 b)
21{
22 J->fold.ins.ot = ot; J->fold.ins.op1 = a; J->fold.ins.op2 = b;
23}
24
25#define lj_ir_set(J, ot, a, b) \
26 lj_ir_set_(J, (uint16_t)(ot), (IRRef1)(a), (IRRef1)(b))
27
28/* Get ref of next IR instruction and optionally grow IR.
29** Note: this may invalidate all IRIns*!
30*/
31static LJ_AINLINE IRRef lj_ir_nextins(jit_State *J)
32{
33 IRRef ref = J->cur.nins;
34 if (LJ_UNLIKELY(ref >= J->irtoplim)) lj_ir_growtop(J);
35 J->cur.nins = ref + 1;
36 return ref;
37}
38
39/* Interning of constants. */
40LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k);
41LJ_FUNC void lj_ir_k64_freeall(jit_State *J);
42LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv);
43LJ_FUNC cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64);
44LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64);
45LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n);
46LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64);
47LJ_FUNC TRef lj_ir_kgc(jit_State *J, GCobj *o, IRType t);
48LJ_FUNC TRef lj_ir_kptr_(jit_State *J, IROp op, void *ptr);
49LJ_FUNC TRef lj_ir_knull(jit_State *J, IRType t);
50LJ_FUNC TRef lj_ir_kslot(jit_State *J, TRef key, IRRef slot);
51
52#if LJ_64
53#define lj_ir_kintp(J, k) lj_ir_kint64(J, (uint64_t)(k))
54#else
55#define lj_ir_kintp(J, k) lj_ir_kint(J, (int32_t)(k))
56#endif
57
58static LJ_AINLINE TRef lj_ir_knum(jit_State *J, lua_Number n)
59{
60 TValue tv;
61 tv.n = n;
62 return lj_ir_knum_u64(J, tv.u64);
63}
64
65#define lj_ir_kstr(J, str) lj_ir_kgc(J, obj2gco((str)), IRT_STR)
66#define lj_ir_ktab(J, tab) lj_ir_kgc(J, obj2gco((tab)), IRT_TAB)
67#define lj_ir_kfunc(J, func) lj_ir_kgc(J, obj2gco((func)), IRT_FUNC)
68#define lj_ir_kptr(J, ptr) lj_ir_kptr_(J, IR_KPTR, (ptr))
69#define lj_ir_kkptr(J, ptr) lj_ir_kptr_(J, IR_KKPTR, (ptr))
70
71/* Special FP constants. */
72#define lj_ir_knum_zero(J) lj_ir_knum_u64(J, U64x(00000000,00000000))
73#define lj_ir_knum_one(J) lj_ir_knum_u64(J, U64x(3ff00000,00000000))
74#define lj_ir_knum_tobit(J) lj_ir_knum_u64(J, U64x(43380000,00000000))
75
76/* Special 128 bit SIMD constants. */
77#define lj_ir_knum_abs(J) lj_ir_k64(J, IR_KNUM, LJ_KSIMD(J, LJ_KSIMD_ABS))
78#define lj_ir_knum_neg(J) lj_ir_k64(J, IR_KNUM, LJ_KSIMD(J, LJ_KSIMD_NEG))
79
80/* Access to constants. */
81LJ_FUNC void lj_ir_kvalue(lua_State *L, TValue *tv, const IRIns *ir);
82
83/* Convert IR operand types. */
84LJ_FUNC TRef LJ_FASTCALL lj_ir_tonumber(jit_State *J, TRef tr);
85LJ_FUNC TRef LJ_FASTCALL lj_ir_tonum(jit_State *J, TRef tr);
86LJ_FUNC TRef LJ_FASTCALL lj_ir_tostr(jit_State *J, TRef tr);
87
88/* Miscellaneous IR ops. */
89LJ_FUNC int lj_ir_numcmp(lua_Number a, lua_Number b, IROp op);
90LJ_FUNC int lj_ir_strcmp(GCstr *a, GCstr *b, IROp op);
91LJ_FUNC void lj_ir_rollback(jit_State *J, IRRef ref);
92
93/* Emit IR instructions with on-the-fly optimizations. */
94LJ_FUNC TRef LJ_FASTCALL lj_opt_fold(jit_State *J);
95LJ_FUNC TRef LJ_FASTCALL lj_opt_cse(jit_State *J);
96LJ_FUNC TRef LJ_FASTCALL lj_opt_cselim(jit_State *J, IRRef lim);
97
98/* Special return values for the fold functions. */
99enum {
100 NEXTFOLD, /* Couldn't fold, pass on. */
101 RETRYFOLD, /* Retry fold with modified fins. */
102 KINTFOLD, /* Return ref for int constant in fins->i. */
103 FAILFOLD, /* Guard would always fail. */
104 DROPFOLD, /* Guard eliminated. */
105 MAX_FOLD
106};
107
108#define INTFOLD(k) ((J->fold.ins.i = (k)), (TRef)KINTFOLD)
109#define INT64FOLD(k) (lj_ir_kint64(J, (k)))
110#define CONDFOLD(cond) ((TRef)FAILFOLD + (TRef)(cond))
111#define LEFTFOLD (J->fold.ins.op1)
112#define RIGHTFOLD (J->fold.ins.op2)
113#define CSEFOLD (lj_opt_cse(J))
114#define EMITFOLD (lj_ir_emit(J))
115
116/* Load/store forwarding. */
117LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_aload(jit_State *J);
118LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hload(jit_State *J);
119LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_uload(jit_State *J);
120LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_fload(jit_State *J);
121LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_xload(jit_State *J);
122LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J);
123LJ_FUNC TRef LJ_FASTCALL lj_opt_fwd_hrefk(jit_State *J);
124LJ_FUNC int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J);
125LJ_FUNC int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim);
126LJ_FUNC int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref);
127
128/* Dead-store elimination. */
129LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J);
130LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_ustore(jit_State *J);
131LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_fstore(jit_State *J);
132LJ_FUNC TRef LJ_FASTCALL lj_opt_dse_xstore(jit_State *J);
133
134/* Narrowing. */
135LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_convert(jit_State *J);
136LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_index(jit_State *J, TRef key);
137LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_toint(jit_State *J, TRef tr);
138LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_tobit(jit_State *J, TRef tr);
139#if LJ_HASFFI
140LJ_FUNC TRef LJ_FASTCALL lj_opt_narrow_cindex(jit_State *J, TRef key);
141#endif
142LJ_FUNC TRef lj_opt_narrow_arith(jit_State *J, TRef rb, TRef rc,
143 TValue *vb, TValue *vc, IROp op);
144LJ_FUNC TRef lj_opt_narrow_unm(jit_State *J, TRef rc, TValue *vc);
145LJ_FUNC TRef lj_opt_narrow_mod(jit_State *J, TRef rb, TRef rc, TValue *vc);
146LJ_FUNC TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc);
147LJ_FUNC IRType lj_opt_narrow_forl(jit_State *J, cTValue *forbase);
148
149/* Optimization passes. */
150LJ_FUNC void lj_opt_dce(jit_State *J);
151LJ_FUNC int lj_opt_loop(jit_State *J);
152#if LJ_SOFTFP || (LJ_32 && LJ_HASFFI)
153LJ_FUNC void lj_opt_split(jit_State *J);
154#else
155#define lj_opt_split(J) UNUSED(J)
156#endif
157LJ_FUNC void lj_opt_sink(jit_State *J);
158
159#endif
160
161#endif
162