From 159f51d8113555853a3325462f802010d4aac024 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 6 Dec 2010 16:18:18 +0100 Subject: [PATCH] Add IR_TOI64. --- lib/dump.lua | 6 ++++-- src/lj_asm.c | 19 +++++++++++++++++++ src/lj_ir.h | 8 ++++++-- src/lj_opt_fold.c | 26 ++++++++++++++++++++++++++ src/lj_target_x86.h | 1 + 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/dump.lua b/lib/dump.lua index 3c726484..687d79db 100644 --- a/lib/dump.lua +++ b/lib/dump.lua @@ -219,7 +219,8 @@ span.irt_int, span.irt_i8, span.irt_u8, span.irt_i16, span.irt_u16 { color: #b04 local colorize, irtype --- Lookup table to convert some literals into names. +-- Lookup tables to convert some literals into names. +local tointname = { [0] = "check", "index", "", "Z", "S", "T", } local litname = { ["SLOAD "] = setmetatable({}, { __index = function(t, mode) local s = "" @@ -233,7 +234,8 @@ local litname = { return s end}), ["XLOAD "] = { [0] = "", "R", "U", "RU", }, - ["TOINT "] = { [0] = "check", "index", "", }, + ["TOINT "] = tointname, + ["TOI64 "] = tointname, ["FLOAD "] = vmdef.irfield, ["FREF "] = vmdef.irfield, ["FPMATH"] = vmdef.irfpm, diff --git a/src/lj_asm.c b/src/lj_asm.c index 81529a56..e05de41e 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1595,6 +1595,24 @@ static void asm_tobit(ASMState *as, IRIns *ir) ra_left(as, tmp, ir->op1); } +static void asm_toi64(ASMState *as, IRIns *ir) +{ + Reg dest = ra_dest(as, ir, RSET_GPR); + IRRef lref = ir->op1; + lua_assert(LJ_64); /* NYI: 32 bit register pairs. */ + if (ir->op2 == IRTOINT_TRUNCI64) { + Reg left = asm_fuseload(as, lref, RSET_FPR); + emit_mrm(as, XO_CVTTSD2SI, dest|REX_64, left); + } else if (ir->op2 == IRTOINT_ZEXT64) { + /* Nothing to do. This assumes 32 bit regs are already zero-extended. */ + ra_left(as, dest, lref); /* But may need to move regs. */ + } else { + Reg left = asm_fuseload(as, lref, RSET_GPR); + emit_mrm(as, XO_MOVSXd, dest|REX_64, left); + lua_assert(ir->op2 == IRTOINT_SEXT64); + } +} + static void asm_strto(ASMState *as, IRIns *ir) { /* Force a spill slot for the destination register (if any). */ @@ -3531,6 +3549,7 @@ static void asm_ir(ASMState *as, IRIns *ir) asm_toint(as, ir); break; break; case IR_TOBIT: asm_tobit(as, ir); break; + case IR_TOI64: asm_toi64(as, ir); break; case IR_TOSTR: asm_tostr(as, ir); break; case IR_STRTO: asm_strto(as, ir); break; diff --git a/src/lj_ir.h b/src/lj_ir.h index 72a4d6b4..72c37343 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h @@ -119,6 +119,7 @@ _(TONUM, N , ref, ___) \ _(TOINT, N , ref, lit) \ _(TOBIT, N , ref, ref) \ + _(TOI64, N , ref, lit) \ _(TOSTR, N , ref, ___) \ _(STRTO, N , ref, ___) \ \ @@ -204,11 +205,14 @@ IRFLDEF(FLENUM) #define IRXLOAD_READONLY 1 /* Load from read-only data. */ #define IRXLOAD_UNALIGNED 2 /* Unaligned load. */ -/* TOINT mode, stored in op2. Ordered by strength of the checks. */ +/* TOINT/TOI64 mode, stored in op2. Ordered by strength of the checks. */ #define IRTOINT_CHECK 0 /* Number checked for integerness. */ #define IRTOINT_INDEX 1 /* Checked + special backprop rules. */ #define IRTOINT_ANY 2 /* Any FP number is ok. */ -#define IRTOINT_TOBIT 3 /* Cache only: TOBIT conversion. */ +#define IRTOINT_ZEXT64 3 /* Convert uint32_t to int64_t. */ +#define IRTOINT_SEXT64 4 /* Convert int32_t to int64_t. */ +#define IRTOINT_TRUNCI64 5 /* Truncate number to int64_t. */ +#define IRTOINT_TOBIT 6 /* Cache only: TOBIT conversion. */ /* C call info for CALL* instructions. */ typedef struct CCallInfo { diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index feddba87..cf5de82f 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c @@ -270,6 +270,23 @@ LJFOLDF(kfold_toint) return INTFOLD(k); } +LJFOLD(TOI64 KINT any) +LJFOLDF(kfold_toi64_kint) +{ + lua_assert(fins->op2 == IRTOINT_ZEXT64 || fins->op2 == IRTOINT_SEXT64); + if (fins->op2 == IRTOINT_ZEXT64) + return lj_ir_kint64(J, (int64_t)(uint32_t)fleft->i); + else + return lj_ir_kint64(J, (int64_t)(int32_t)fleft->i); +} + +LJFOLD(TOI64 KNUM any) +LJFOLDF(kfold_toi64_knum) +{ + lua_assert(fins->op2 == IRTOINT_TRUNCI64); + return lj_ir_kint64(J, (int64_t)knumleft); +} + LJFOLD(TOSTR KNUM) LJFOLDF(kfold_tostr_knum) { @@ -471,6 +488,15 @@ LJFOLDF(shortcut_leftleft_across_phi) return fleft->op1; /* f(g(x)) ==> x */ } +LJFOLD(TOI64 TONUM any) +LJFOLDF(shortcut_leftleft_toint64) +{ + /* Fold even across PHI to avoid expensive int->num->int64 conversions. */ + fins->op1 = fleft->op1; /* (int64_t)(double)(int)x ==> (int64_t)x */ + fins->op2 = IRTOINT_SEXT64; + return RETRYFOLD; +} + /* -- FP algebraic simplifications ---------------------------------------- */ /* FP arithmetic is tricky -- there's not much to simplify. diff --git a/src/lj_target_x86.h b/src/lj_target_x86.h index d3956a09..bf58d67c 100644 --- a/src/lj_target_x86.h +++ b/src/lj_target_x86.h @@ -230,6 +230,7 @@ typedef enum { XO_MOVZXw = XO_0f(b7), XO_MOVSXb = XO_0f(be), XO_MOVSXw = XO_0f(bf), + XO_MOVSXd = XO_(63), XO_BSWAP = XO_0f(c8), XO_MOVSD = XO_f20f(10),