master: Optimize (BOUNDP 'known-symbol) if #+tls-load-indirect

snuglas via Sbcl-commits <[email protected]>
Newsgroups gmane.lisp.steel-bank.cvs
Message-ID <[email protected]>
The branch "master" has been updated in SBCL:
       via  6094278bbe5646ef4472e37a61ecb7bab395aff5 (commit)
      from  2d87e918aa7e7685dc3e87d21c1547bc1d74c201 (commit)

- Log -----------------------------------------------------------------
commit 6094278bbe5646ef4472e37a61ecb7bab395aff5
Author: Douglas Katzman <[email protected]>
Date:   Tue Apr 7 19:57:09 2026 -0400

    Optimize (BOUNDP 'known-symbol) if #+tls-load-indirect
---
 src/compiler/x86-64/tls.lisp |  5 +++++
 src/runtime/x86-64-arch.c    | 39 ++++++++++++++++++++++++++++++---------
 2 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/src/compiler/x86-64/tls.lisp b/src/compiler/x86-64/tls.lisp
index f5f6ee15b..3d310e38b 100644
--- a/src/compiler/x86-64/tls.lisp
+++ b/src/compiler/x86-64/tls.lisp
@@ -282,6 +282,11 @@
                             (t
                              (symbol-slot-ea (tn-value symbol) symbol-value-slot)))
             unbound-marker-widetag))
+     #+tls-load-indirect
+     ((sc-is symbol immediate constant) ; 2 instructions, possibly handling a load fault
+      (inst mov temp (thread-tls-ea (load-time-tls-offset (tn-value symbol) -8)))
+      (push (emit-label (gen-label)) (sb-assem::asmstream-eh-locs sb-assem:*asmstream*))
+      (inst cmp :byte (ea 1 temp) unbound-marker-widetag))
      (t
       ;; For a known symbol that is not known to be either aways global or thread-local,
       ;; wire in a TLS index. It's unlikely that TLS will be exhausted by doing this, in contrast
diff --git a/src/runtime/x86-64-arch.c b/src/runtime/x86-64-arch.c
index 39c7cad32..28fd6a723 100644
--- a/src/runtime/x86-64-arch.c
+++ b/src/runtime/x86-64-arch.c
@@ -917,29 +917,50 @@ int handle_tls_deref_trap(os_context_t* context, os_vm_address_t addr)
 {
     unsigned char* pc = (void*)os_context_pc(context);
     if (!(addr == 0 && gc_managed_heap_space_p((lispobj)pc))) return 0;
+
+    int variant = 0;
+    // Check that the faulting instruction has one of two forms:
+    //   * MOV Rd,[Rn+1]
+    //   * CMP BYTE PTR [Rn+1], UNBOUND-MARKER-WIDETAG
+    if (((pc[0] == 0x48 || pc[0] == 0x4D) && pc[1] == 0x8B &&
+         (pc[2] & 0300) == 0100 && pc[3] == 1)) {
+        variant = 1; // MOV instruction
+    } else if (pc[0] == 0x80 && (pc[1] & 0370) == 0170 && pc[2] == 1 &&
+               pc[3] == UNBOUND_MARKER_WIDETAG) {
+        // 1 = (SYMBOL_VALUE_SLOT << WORD_SHIFT) - OTHER_POINTER_LOWTAG
+        variant = 2; // CMP instruction with no REX prefix
+    } else if (pc[0] == 0x41 && pc[1] == 0x80 && (pc[2] & 0370) == 0170 &&
+               pc[3] == 1 && pc[4] == UNBOUND_MARKER_WIDETAG) {
+        variant = 3; // CMP using any of R8 through R15
+    } else {
+      return 0;
+    }
+
     struct code* code = (void*)component_ptr_from_pc((char*)pc);
     if (!code) return 0;
     struct compiled_debug_info* cdi = (void*)native_pointer(code->debug_info);
     if (cdi->eh_locs == NIL) return 0;
 
-    // Check that the faulting instruction is MOV Rd,[Rn+1]
-    if ((pc[0] == 0x48 || pc[0] == 0x4D) && pc[1] == 0x8B &&
-        (pc[2] & 0300) == 0100 && pc[3] == 1) {
-    } else {
-      return 0;
-    }
     struct vector* eh_locs = VECTOR(cdi->eh_locs);
     uint32_t* data = (void*)eh_locs->data;
     uint32_t pc_offset = (char*)pc - code_text_start(code);
     int i = bsearch_greatereql_uint32(pc_offset, data, vector_len(eh_locs));
     if (i<0 || data[i] != pc_offset) return 0;
 
-    pc -= 7;
-    int32_t disp = UNALIGNED_LOAD32(pc+3);
+    int32_t disp;
+    switch (variant) {
+    case 1: case 2: case 3:
+        // The instruction preceding the faulting one is always 7 bytes:
+        //   498B85700F0000  MOV RAX, [R13+disp32]
+        pc -= 7;
+        disp = UNALIGNED_LOAD32(pc+3);
+        break;
+    }
     int logical_index = disp >> (1+WORD_SHIFT);
     lispobj symbol = tlsindex_to_symbol_map[logical_index];
     gc_assert(symbol != NO_TLS_VALUE_MARKER);
-    //fprintf(stderr, "TLS trap handled: %s\n", (char*)VECTOR(SYMBOL(symbol)->name)->data);
+    /*fprintf(stderr, "TLS trap variant %d for %s\n", variant,
+            (char*)VECTOR(SYMBOL(symbol)->name)->data);*/
     struct thread* th = get_sb_vm_thread();
     lispobj* pcell = (lispobj*)(disp + (char*)th);
     lispobj value = pcell[1];

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.