From 255dc0ec0b79c354bff017f6d6202adaa092a1c9 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Thu, 14 May 2026 23:48:57 -0400 Subject: vt: merge ucs_is_zero_width()/ucs_is_double_width() into ucs_get_width() The hot path in vc_process_ucs() asks two independent questions about the same code point -- "is it double-width?" and "is it zero-width?" -- and was answering each with its own bsearch over its own table. For anything past the leading bounds check that meant two scans of the BMP width tables back to back for what is logically a single lookup. Replace both with one ucs_get_width(cp) returning 0, 1, or 2 in a single bsearch, while keeping the total table footprint at the same 2384 B as before. To do so, merge the zero-width and double-width ranges per region into one sorted-by-`first` table. BMP entries stay 4 bytes; per-entry width is hosted in spare bits of the non-BMP table's `last` field. Non-BMP code points use only 20 of 32 bits, so each u32 has 12 unused high bits. Store first/last shifted left by 12 and use the low 12 bits of `last` for metadata: bit 11 is this entry's own width flag, bits 0..7 host an 8-bit chunk of the BMP double-width bitmap. Because the metadata bits sit strictly below the lowest cp-scale bit, the bsearch comparator remains a plain u32 compare on shifted keys with no masking. In vc_process_ucs() the overwhelmingly common single-width path now collapses to a single predicted branch: if (likely(w == 1)) return 1; Note: scripts/checkpatch.pl complains about "Macros with complex values should be enclosed in parentheses" for the BMP_*WIDTH and RANGE_*WIDTH macros. They are deliberately defined to expand to a comma-separated (first, last) pair so they can populate the two adjacent fields of a struct initializer; wrapping them in parentheses would turn that into a comma-expression and defeat the whole construction. Please ignore. Signed-off-by: Nicolas Pitre Link: https://patch.msgid.link/20260515034857.2514225-1-nico@fluxnic.net Signed-off-by: Greg Kroah-Hartman --- include/linux/consolemap.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'include/linux/consolemap.h') diff --git a/include/linux/consolemap.h b/include/linux/consolemap.h index 6180b803795c..539d488fdc03 100644 --- a/include/linux/consolemap.h +++ b/include/linux/consolemap.h @@ -28,8 +28,7 @@ int conv_uni_to_pc(struct vc_data *conp, long ucs); u32 conv_8bit_to_uni(unsigned char c); int conv_uni_to_8bit(u32 uni); void console_map_init(void); -bool ucs_is_double_width(uint32_t cp); -bool ucs_is_zero_width(uint32_t cp); +unsigned int ucs_get_width(uint32_t cp); u32 ucs_recompose(u32 base, u32 mark); u32 ucs_get_fallback(u32 cp); #else @@ -62,14 +61,9 @@ static inline int conv_uni_to_8bit(u32 uni) static inline void console_map_init(void) { } -static inline bool ucs_is_double_width(uint32_t cp) +static inline unsigned int ucs_get_width(uint32_t cp) { - return false; -} - -static inline bool ucs_is_zero_width(uint32_t cp) -{ - return false; + return 1; } static inline u32 ucs_recompose(u32 base, u32 mark) -- cgit v1.2.3