diff options
author | Mike Pall <mike> | 2011-03-03 17:29:09 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-03-03 17:29:09 +0100 |
commit | f29a9d4341c64fa47c735bdf6ae1f379b6b6464c (patch) | |
tree | 78582e47199e76dad6309ddd540d070e3f4c16d2 | |
parent | 1cb58fb7bb3cfe455426246599cac32ad5ec57ee (diff) | |
download | luajit-f29a9d4341c64fa47c735bdf6ae1f379b6b6464c.tar.gz luajit-f29a9d4341c64fa47c735bdf6ae1f379b6b6464c.tar.bz2 luajit-f29a9d4341c64fa47c735bdf6ae1f379b6b6464c.zip |
Fix narrowing of POW.
-rw-r--r-- | src/lj_opt_narrow.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c index 71062493..0a2bb6cd 100644 --- a/src/lj_opt_narrow.c +++ b/src/lj_opt_narrow.c | |||
@@ -413,23 +413,27 @@ TRef lj_opt_narrow_pow(jit_State *J, TRef rb, TRef rc, TValue *vc) | |||
413 | if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc)) | 413 | if (tvisstr(vc) && !lj_str_tonum(strV(vc), vc)) |
414 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 414 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
415 | n = numV(vc); | 415 | n = numV(vc); |
416 | /* Limit narrowing for pow to small exponents (or for two constants). */ | 416 | /* Narrowing must be unconditional to preserve (-x)^i semantics. */ |
417 | if ((tref_isk(rc) && tref_isint(rc) && tref_isk(rb)) || | 417 | if (numisint(n)) { |
418 | ((J->flags & JIT_F_OPT_NARROW) && | 418 | int checkrange = 0; |
419 | (numisint(n) && n >= -65536.0 && n <= 65536.0))) { | 419 | /* Split pow is faster for bigger exponents. But do this only for (+k)^i. */ |
420 | TRef tmp; | 420 | if (tref_isk(rb) && (int32_t)ir_knum(IR(tref_ref(rb)))->u32.hi >= 0) { |
421 | if (!(n >= -65536.0 && n <= 65536.0)) goto split_pow; | ||
422 | checkrange = 1; | ||
423 | } | ||
421 | if (!tref_isinteger(rc)) { | 424 | if (!tref_isinteger(rc)) { |
422 | if (tref_isstr(rc)) | 425 | if (tref_isstr(rc)) |
423 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); | 426 | rc = emitir(IRTG(IR_STRTO, IRT_NUM), rc, 0); |
424 | /* Guarded conversion to integer! */ | 427 | /* Guarded conversion to integer! */ |
425 | rc = emitir(IRTGI(IR_CONV), rc, IRCONV_INT_NUM|IRCONV_CHECK); | 428 | rc = emitir(IRTGI(IR_CONV), rc, IRCONV_INT_NUM|IRCONV_CHECK); |
426 | } | 429 | } |
427 | if (!tref_isk(rc)) { /* Range guard: -65536 <= i <= 65536 */ | 430 | if (checkrange && !tref_isk(rc)) { /* Range guard: -65536 <= i <= 65536 */ |
428 | tmp = emitir(IRTI(IR_ADD), rc, lj_ir_kint(J, 65536-2147483647-1)); | 431 | TRef tmp = emitir(IRTI(IR_ADD), rc, lj_ir_kint(J, 65536)); |
429 | emitir(IRTGI(IR_LE), tmp, lj_ir_kint(J, 2*65536-2147483647-1)); | 432 | emitir(IRTGI(IR_ULE), tmp, lj_ir_kint(J, 2*65536)); |
430 | } | 433 | } |
431 | return emitir(IRTN(IR_POW), rb, rc); | 434 | return emitir(IRTN(IR_POW), rb, rc); |
432 | } | 435 | } |
436 | split_pow: | ||
433 | /* FOLD covers most cases, but some are easier to do here. */ | 437 | /* FOLD covers most cases, but some are easier to do here. */ |
434 | if (tref_isk(rb) && tvispone(ir_knum(IR(tref_ref(rb))))) | 438 | if (tref_isk(rb) && tvispone(ir_knum(IR(tref_ref(rb))))) |
435 | return rb; /* 1 ^ x ==> 1 */ | 439 | return rb; /* 1 ^ x ==> 1 */ |