aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2023-09-09 14:11:25 +0200
committerMike Pall <mike>2023-09-09 14:11:25 +0200
commit9daf9f9003ff29551ef3b6fe19f4abf868bfd414 (patch)
tree0d7c2551dd850dd9e221907c1e78a62e9e07650b /src
parent9bd240413706f03cbd619216da9b26a861a6d6e6 (diff)
downloadluajit-9daf9f9003ff29551ef3b6fe19f4abf868bfd414.tar.gz
luajit-9daf9f9003ff29551ef3b6fe19f4abf868bfd414.tar.bz2
luajit-9daf9f9003ff29551ef3b6fe19f4abf868bfd414.zip
ARM64: Improve K13 constant rematerialization.
Algorithm by Dougall Johnson: https://dougallj.wordpress.com/2021/10/30/ Thanks to Peter Cawley. #1065
Diffstat (limited to 'src')
-rw-r--r--src/lj_emit_arm64.h32
1 files changed, 12 insertions, 20 deletions
diff --git a/src/lj_emit_arm64.h b/src/lj_emit_arm64.h
index 6926c71a..7205ce78 100644
--- a/src/lj_emit_arm64.h
+++ b/src/lj_emit_arm64.h
@@ -43,26 +43,18 @@ static uint32_t emit_isk12(int64_t n)
43/* Encode constant in K13 format for logical data processing instructions. */ 43/* Encode constant in K13 format for logical data processing instructions. */
44static uint32_t emit_isk13(uint64_t n, int is64) 44static uint32_t emit_isk13(uint64_t n, int is64)
45{ 45{
46 int inv = 0, w = 128, lz, tz; 46 /* Thanks to: https://dougallj.wordpress.com/2021/10/30/ */
47 if (n & 1) { n = ~n; w = 64; inv = 1; } /* Avoid wrap-around of ones. */ 47 int rot, ones, size, immr, imms;
48 if (!n) return 0; /* Neither all-zero nor all-ones are allowed. */ 48 if (!is64) n = ((uint64_t)n << 32) | (uint32_t)n;
49 do { /* Find the repeat width. */ 49 if ((n+1u) <= 1u) return 0; /* Neither all-zero nor all-ones are allowed. */
50 if (is64 && (uint32_t)(n^(n>>32))) break; 50 rot = (n & (n+1u)) ? emit_ctz64(n & (n+1u)) : 64;
51 n = (uint32_t)n; 51 n = lj_ror(n, rot & 63);
52 if (!n) return 0; /* Ditto when passing n=0xffffffff and is64=0. */ 52 ones = emit_ctz64(~n);
53 w = 32; if ((n^(n>>16)) & 0xffff) break; 53 size = emit_clz64(n) + ones;
54 n = n & 0xffff; w = 16; if ((n^(n>>8)) & 0xff) break; 54 if (lj_ror(n, size & 63) != n) return 0; /* Non-repeating? */
55 n = n & 0xff; w = 8; if ((n^(n>>4)) & 0xf) break; 55 immr = -rot & (size - 1);
56 n = n & 0xf; w = 4; if ((n^(n>>2)) & 0x3) break; 56 imms = (-(size << 1) | (ones - 1)) & 63;
57 n = n & 0x3; w = 2; 57 return A64I_K13 | A64F_IMMR(immr | (size & 64)) | A64F_IMMS(imms);
58 } while (0);
59 lz = emit_clz64(n);
60 tz = emit_ctz64(n);
61 if ((int64_t)(n << lz) >> (lz+tz) != -1ll) return 0; /* Non-contiguous? */
62 if (inv)
63 return A64I_K13 | (((lz-w) & 127) << 16) | (((lz+tz-w-1) & 63) << 10);
64 else
65 return A64I_K13 | ((w-tz) << 16) | (((63-lz-tz-w-w) & 63) << 10);
66} 58}
67 59
68static uint32_t emit_isfpk64(uint64_t n) 60static uint32_t emit_isfpk64(uint64_t n)