mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 23:24:09 +00:00
Refactoring of conversion ops, part 1: add IR_CONV.
This commit is contained in:
parent
06c61d9cea
commit
2ca2de7f0e
@ -236,6 +236,15 @@ local litname = {
|
|||||||
return s
|
return s
|
||||||
end}),
|
end}),
|
||||||
["XLOAD "] = { [0] = "", "R", "U", "RU", },
|
["XLOAD "] = { [0] = "", "R", "U", "RU", },
|
||||||
|
["CONV "] = setmetatable({}, { __index = function(t, mode)
|
||||||
|
local s = irtype[band(mode, 31)]
|
||||||
|
if band(mode, 0x100) ~= 0 then s = s.." trunc"
|
||||||
|
elseif band(mode, 0x200) ~= 0 then s = s.." sext" end
|
||||||
|
local c = shr(mode, 10)
|
||||||
|
if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end
|
||||||
|
t[mode] = s
|
||||||
|
return s
|
||||||
|
end}),
|
||||||
["TOINT "] = tointname,
|
["TOINT "] = tointname,
|
||||||
["TOI64 "] = tointname,
|
["TOI64 "] = tointname,
|
||||||
["FLOAD "] = vmdef.irfield,
|
["FLOAD "] = vmdef.irfield,
|
||||||
|
96
src/lj_asm.c
96
src/lj_asm.c
@ -1654,6 +1654,99 @@ static void asm_toi64(ASMState *as, IRIns *ir)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void asm_conv(ASMState *as, IRIns *ir)
|
||||||
|
{
|
||||||
|
IRType st = (IRType)(ir->op2 & 0x1f);
|
||||||
|
int st64 = (st == IRT_I64 || st == IRT_U64 || (LJ_64 && st == IRT_P64));
|
||||||
|
int stfp = (st == IRT_NUM || st == IRT_FLOAT);
|
||||||
|
IRRef lref = ir->op1;
|
||||||
|
lua_assert(irt_type(ir->t) != st);
|
||||||
|
if (irt_isnum(ir->t) || irt_isfloat(ir->t)) {
|
||||||
|
Reg dest = ra_dest(as, ir, RSET_FPR);
|
||||||
|
if (stfp) { /* FP to FP conversion. */
|
||||||
|
Reg left = asm_fuseload(as, lref, RSET_FPR);
|
||||||
|
emit_mrm(as, st == IRT_NUM ? XO_CVTSD2SS : XO_CVTSS2SD, dest, left);
|
||||||
|
if (left == dest) return; /* Avoid the XO_XORPS. */
|
||||||
|
#if LJ_32
|
||||||
|
} else if (st >= IRT_U32) {
|
||||||
|
/* NYI: 64 bit integer or uint32_t to number conversion. */
|
||||||
|
setintV(&as->J->errinfo, ir->o);
|
||||||
|
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
} else { /* Integer to FP conversion. */
|
||||||
|
Reg left = (LJ_64 && st == IRT_U32) ? ra_allocref(as, lref, RSET_GPR) :
|
||||||
|
asm_fuseload(as, lref, RSET_GPR);
|
||||||
|
emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS,
|
||||||
|
dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left);
|
||||||
|
}
|
||||||
|
if (!(as->flags & JIT_F_SPLIT_XMM))
|
||||||
|
emit_rr(as, XO_XORPS, dest, dest); /* Avoid partial register stall. */
|
||||||
|
} else if (stfp) { /* FP to integer conversion. */
|
||||||
|
if (irt_isguard(ir->t)) {
|
||||||
|
lua_assert(!irt_is64(ir->t)); /* No support for checked 64 bit conv. */
|
||||||
|
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
|
||||||
|
#if LJ_32
|
||||||
|
} else if (irt_isi64(ir->t) || irt_isu64(ir->t) || irt_isu32(ir->t)) {
|
||||||
|
/* NYI: number to 64 bit integer or uint32_t conversion. */
|
||||||
|
setintV(&as->J->errinfo, ir->o);
|
||||||
|
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||||
|
#else
|
||||||
|
} else if (irt_isu64(ir->t)) {
|
||||||
|
/* NYI: number to uint64_t conversion. */
|
||||||
|
setintV(&as->J->errinfo, ir->o);
|
||||||
|
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
|
Reg left = asm_fuseload(as, ir->op1, RSET_FPR);
|
||||||
|
x86Op op = st == IRT_NUM ?
|
||||||
|
((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) :
|
||||||
|
((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI);
|
||||||
|
if (LJ_64 && irt_isu32(ir->t))
|
||||||
|
emit_rr(as, XO_MOV, dest, dest); /* Zero upper 32 bits. */
|
||||||
|
emit_mrm(as, op,
|
||||||
|
dest|((LJ_64 &&
|
||||||
|
(irt_is64(ir->t) || irt_isu32(ir->t))) ? REX_64 : 0),
|
||||||
|
left);
|
||||||
|
}
|
||||||
|
} else { /* Integer to integer conversion. Only need 32/64 bit variants. */
|
||||||
|
if (irt_is64(ir->t)) {
|
||||||
|
#if LJ_32
|
||||||
|
/* NYI: conversion to 64 bit integers. */
|
||||||
|
setintV(&as->J->errinfo, ir->o);
|
||||||
|
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||||
|
#else
|
||||||
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
|
if (st64 || !(ir->op2 & IRCONV_SEXT)) {
|
||||||
|
/* 64/64 bit no-op (cast) or 32 to 64 bit zero extension. */
|
||||||
|
ra_left(as, dest, lref); /* Do nothing, but may need to move regs. */
|
||||||
|
} else { /* 32 to 64 bit sign extension. */
|
||||||
|
Reg left = asm_fuseload(as, lref, RSET_GPR);
|
||||||
|
emit_mrm(as, XO_MOVSXd, dest|REX_64, left);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
Reg dest = ra_dest(as, ir, RSET_GPR);
|
||||||
|
if (st64) {
|
||||||
|
#if LJ_32
|
||||||
|
/* NYI: conversion from 64 bit integers. */
|
||||||
|
setintV(&as->J->errinfo, ir->o);
|
||||||
|
lj_trace_err_info(as->J, LJ_TRERR_NYIIR);
|
||||||
|
#else
|
||||||
|
Reg left = asm_fuseload(as, lref, RSET_GPR);
|
||||||
|
/* This is either a 32 bit reg/reg mov which zeroes the hi-32 bits
|
||||||
|
** or a load of the lower 32 bits from a 64 bit address.
|
||||||
|
*/
|
||||||
|
emit_mrm(as, XO_MOV, dest, left);
|
||||||
|
#endif
|
||||||
|
} else { /* 32/32 bit no-op (cast). */
|
||||||
|
ra_left(as, dest, lref); /* Do nothing, but may need to move regs. */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void asm_strto(ASMState *as, IRIns *ir)
|
static void asm_strto(ASMState *as, IRIns *ir)
|
||||||
{
|
{
|
||||||
/* Force a spill slot for the destination register (if any). */
|
/* Force a spill slot for the destination register (if any). */
|
||||||
@ -3666,6 +3759,7 @@ static void asm_ir(ASMState *as, IRIns *ir)
|
|||||||
break;
|
break;
|
||||||
case IR_TOBIT: asm_tobit(as, ir); break;
|
case IR_TOBIT: asm_tobit(as, ir); break;
|
||||||
case IR_TOI64: asm_toi64(as, ir); break;
|
case IR_TOI64: asm_toi64(as, ir); break;
|
||||||
|
case IR_CONV: asm_conv(as, ir); break;
|
||||||
case IR_TOSTR: asm_tostr(as, ir); break;
|
case IR_TOSTR: asm_tostr(as, ir); break;
|
||||||
case IR_STRTO: asm_strto(as, ir); break;
|
case IR_STRTO: asm_strto(as, ir); break;
|
||||||
|
|
||||||
@ -3808,7 +3902,7 @@ static void asm_setup_regsp(ASMState *as, GCtrace *T)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* Do not propagate hints across type conversions. */
|
/* Do not propagate hints across type conversions. */
|
||||||
case IR_TONUM: case IR_TOINT: case IR_TOBIT:
|
case IR_CONV: case IR_TONUM: case IR_TOINT: case IR_TOBIT:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Propagate hints across likely 'op reg, imm' or 'op reg'. */
|
/* Propagate hints across likely 'op reg, imm' or 'op reg'. */
|
||||||
|
11
src/lj_ir.h
11
src/lj_ir.h
@ -118,6 +118,7 @@
|
|||||||
_(OBAR, S , ref, ref) \
|
_(OBAR, S , ref, ref) \
|
||||||
\
|
\
|
||||||
/* Type conversions. */ \
|
/* Type conversions. */ \
|
||||||
|
_(CONV, N , ref, lit) \
|
||||||
_(TONUM, N , ref, ___) \
|
_(TONUM, N , ref, ___) \
|
||||||
_(TOINT, N , ref, lit) \
|
_(TOINT, N , ref, lit) \
|
||||||
_(TOBIT, N , ref, ref) \
|
_(TOBIT, N , ref, ref) \
|
||||||
@ -218,6 +219,16 @@ IRFLDEF(FLENUM)
|
|||||||
#define IRTOINT_TRUNCI64 5 /* Truncate number to int64_t. */
|
#define IRTOINT_TRUNCI64 5 /* Truncate number to int64_t. */
|
||||||
#define IRTOINT_TOBIT 6 /* Cache only: TOBIT conversion. */
|
#define IRTOINT_TOBIT 6 /* Cache only: TOBIT conversion. */
|
||||||
|
|
||||||
|
/* CONV mode, stored in op2. Lowest 8 bits is the IRType of the source. */
|
||||||
|
#define IRCONV_TRUNC 0x100 /* Truncate number to integer. */
|
||||||
|
#define IRCONV_SEXT 0x200 /* Sign-extend integer to integer. */
|
||||||
|
#define IRCONV_CSH 10
|
||||||
|
/* Number to integer conversion mode. Ordered by strength of the checks. */
|
||||||
|
#define IRCONV_TOBIT (0<<IRCONV_CSH) /* None. Cache only: TOBIT conv. */
|
||||||
|
#define IRCONV_ANY (1<<IRCONV_CSH) /* Any FP number is ok. */
|
||||||
|
#define IRCONV_INDEX (2<<IRCONV_CSH) /* Check + special backprop rules. */
|
||||||
|
#define IRCONV_CHECK (3<<IRCONV_CSH) /* Number checked for integerness. */
|
||||||
|
|
||||||
/* C call info for CALL* instructions. */
|
/* C call info for CALL* instructions. */
|
||||||
typedef struct CCallInfo {
|
typedef struct CCallInfo {
|
||||||
ASMFunction func; /* Function pointer. */
|
ASMFunction func; /* Function pointer. */
|
||||||
|
@ -771,6 +771,28 @@ LJFOLDF(cse_toint)
|
|||||||
return EMITFOLD; /* No fallthrough to regular CSE. */
|
return EMITFOLD; /* No fallthrough to regular CSE. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Special CSE rule for CONV. */
|
||||||
|
LJFOLD(CONV any any)
|
||||||
|
LJFOLDF(cse_conv)
|
||||||
|
{
|
||||||
|
if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) {
|
||||||
|
IRRef op1 = fins->op1, op2 = (fins->op2 & IRCONV_MODEMASK);
|
||||||
|
uint8_t guard = irt_isguard(fins->t);
|
||||||
|
IRRef ref = J->chain[IR_CONV];
|
||||||
|
while (ref > op1) {
|
||||||
|
IRIns *ir = IR(ref);
|
||||||
|
/* CSE also depends on the target type!
|
||||||
|
** OTOH commoning with stronger checks is ok, too.
|
||||||
|
*/
|
||||||
|
if (ir->op1 == op1 && irt_sametype(ir->t, fins->t) &&
|
||||||
|
(ir->op2 & IRCONV_MODEMASK) == op2 && irt_isguard(ir->t) >= guard)
|
||||||
|
return ref;
|
||||||
|
ref = ir->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EMITFOLD; /* No fallthrough to regular CSE. */
|
||||||
|
}
|
||||||
|
|
||||||
/* -- Strength reduction of widening -------------------------------------- */
|
/* -- Strength reduction of widening -------------------------------------- */
|
||||||
|
|
||||||
LJFOLD(TOI64 any 3) /* IRTOINT_ZEXT64 */
|
LJFOLD(TOI64 any 3) /* IRTOINT_ZEXT64 */
|
||||||
|
@ -251,6 +251,11 @@ typedef enum {
|
|||||||
XO_CVTSI2SD = XO_f20f(2a),
|
XO_CVTSI2SD = XO_f20f(2a),
|
||||||
XO_CVTSD2SI = XO_f20f(2d),
|
XO_CVTSD2SI = XO_f20f(2d),
|
||||||
XO_CVTTSD2SI= XO_f20f(2c),
|
XO_CVTTSD2SI= XO_f20f(2c),
|
||||||
|
XO_CVTSI2SS = XO_f30f(2a),
|
||||||
|
XO_CVTSS2SI = XO_f30f(2d),
|
||||||
|
XO_CVTTSS2SI= XO_f30f(2c),
|
||||||
|
XO_CVTSS2SD = XO_f30f(5a),
|
||||||
|
XO_CVTSD2SS = XO_f20f(5a),
|
||||||
XO_MOVD = XO_660f(6e),
|
XO_MOVD = XO_660f(6e),
|
||||||
XO_MOVDto = XO_660f(7e),
|
XO_MOVDto = XO_660f(7e),
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user