Message ID | CAMe9rOpTMDecZpBSmYPUfWRaXjxofVFB1NpFzFGpEP=Byfk_jQ@mail.gmail.com |
---|---|
State | Superseded |
Headers |
Return-Path: <libc-alpha-bounces@sourceware.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DECFB3858D33; Mon, 15 Mar 2021 13:30:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DECFB3858D33 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615815038; bh=VC3DB9QybngFPVAz/qQ1/dTlt2opEYraZqSIqyQIf8k=; h=References:In-Reply-To:Date:Subject:To:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=rM/OQcDketjCxxpcBj+ropdhXKhiLwQLB7166IwWG7qNCUCs2doOwjYfzTnDtUPho +EGec3JVaIUmaKnfF1NoLavDF87UfUUFKk2VIhHOY2svhZj3+ivNI2hQGa7blN56SQ TytIie+4tSMctoLFByhrJsgisE2+jJgwsiWBvKCQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-oi1-x234.google.com (mail-oi1-x234.google.com [IPv6:2607:f8b0:4864:20::234]) by sourceware.org (Postfix) with ESMTPS id 2D6863858D29 for <libc-alpha@sourceware.org>; Mon, 15 Mar 2021 13:30:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2D6863858D29 Received: by mail-oi1-x234.google.com with SMTP id y131so31604540oia.8 for <libc-alpha@sourceware.org>; Mon, 15 Mar 2021 06:30:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=VC3DB9QybngFPVAz/qQ1/dTlt2opEYraZqSIqyQIf8k=; b=KTz3dwEtZYjGc4EDpEc0g6RUK/FpWMWy4sha67DbFco6nO/8irOCWoDyDuwMz6P3fd qa5BBZ4zXbjZUmFAjtheScq6/wFROZnUkrvTXi+hTzMPHOEFdg6DI3WHbbcD8PoOnKAv DVNPaq9PGHCvQeO4Pu6VVtukxbJSUjYh0ILIhaUiTR0GjLvZjIY+bssapw1Avc938Sq5 XpyPwEZqFaLWgIlbj9cCCfQRHoTsqmEmBTNbfw/akPNTlCGiy8hIq4LdHQX9XSa9XMS2 o06oXhtAAYRuOSAUlKQ0XD0IkJoiongVzaoJITH4KnuxqFIv9imVRqJ6OjB1lhiecIRO 6+GA== X-Gm-Message-State: AOAM533iOK/imtHN/8sRzChlYSE/jzifxqgxhp8zmMp8lCTYO1smRf8s ecwJEHkXs6HO4nNFgMkBA7baDT10/Sr/ic1rwPR/645B X-Google-Smtp-Source: ABdhPJz3hxJAW+a/zVi6LmSW2n4DqXYEfvWTNQs3Ud/vQNYw0e05n+gLwhpstSXxJ6pabLA6L2RkOSmtfqEXa1L/upY= X-Received: by 2002:a54:468f:: with SMTP id k15mr18572786oic.58.1615815035582; Mon, 15 Mar 2021 06:30:35 -0700 (PDT) MIME-Version: 1.0 References: <20210202191209.4036619-1-hjl.tools@gmail.com> <a077ae86-ebcd-0838-1a6c-e36ec9dbd78f@redhat.com> <CAMe9rOoYT36HpmoBz9NpnOsK+Q_-T8v7TQpdBBNzwvvTnCCuEg@mail.gmail.com> <60a3a304-7f33-3727-a39a-5420d26d13a0@redhat.com> <CAMe9rOrXqn2=00FT4Rw2Eq7q9y_uCXYZ=nxd3LMOtSv9RJNg+Q@mail.gmail.com> <e531c465-b41a-adba-051e-c7b9665fb4eb@redhat.com> In-Reply-To: <e531c465-b41a-adba-051e-c7b9665fb4eb@redhat.com> Date: Mon, 15 Mar 2021 06:29:59 -0700 Message-ID: <CAMe9rOpTMDecZpBSmYPUfWRaXjxofVFB1NpFzFGpEP=Byfk_jQ@mail.gmail.com> Subject: [PATCH v4] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64 To: "Carlos O'Donell" <carlos@redhat.com> Content-Type: multipart/mixed; boundary="000000000000381c0205bd934124" X-Spam-Status: No, score=-3035.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list <libc-alpha.sourceware.org> List-Unsubscribe: <https://sourceware.org/mailman/options/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=unsubscribe> List-Archive: <https://sourceware.org/pipermail/libc-alpha/> List-Post: <mailto:libc-alpha@sourceware.org> List-Help: <mailto:libc-alpha-request@sourceware.org?subject=help> List-Subscribe: <https://sourceware.org/mailman/listinfo/libc-alpha>, <mailto:libc-alpha-request@sourceware.org?subject=subscribe> From: "H.J. Lu via Libc-alpha" <libc-alpha@sourceware.org> Reply-To: "H.J. Lu" <hjl.tools@gmail.com> Cc: GNU C Library <libc-alpha@sourceware.org> Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" <libc-alpha-bounces@sourceware.org> |
Series |
[v4] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64
|
|
Commit Message
H.J. Lu
March 15, 2021, 1:29 p.m. UTC
On Mon, Mar 15, 2021 at 5:49 AM Carlos O'Donell <carlos@redhat.com> wrote: > > On 3/8/21 7:09 PM, H.J. Lu wrote: > > On Mon, Mar 8, 2021 at 2:28 PM Carlos O'Donell <carlos@redhat.com> wrote: > >> > >> On 3/2/21 9:21 AM, H.J. Lu wrote: > >>> On Mon, Mar 1, 2021 at 5:30 AM Carlos O'Donell <carlos@redhat.com> wrote: > >>>> > >>>> On 2/2/21 2:12 PM, H.J. Lu via Libc-alpha wrote: > >>>>> Since there is only "movq imm32s, mem64" and no "movq imm64, mem64", use > >>>>> "movq reg64, mem64" to store 64-bit constant in TCB. > >>>>> --- > >>>>> sysdeps/x86_64/nptl/tls.h | 11 +++++++++++ > >>>>> 1 file changed, 11 insertions(+) > >>>>> > >>>>> diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h > >>>>> index 20f0958780..9ec8703e45 100644 > >>>>> --- a/sysdeps/x86_64/nptl/tls.h > >>>>> +++ b/sysdeps/x86_64/nptl/tls.h > >>>>> @@ -269,6 +269,11 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > >>>>> asm volatile ("movl %0,%%fs:%P1" : \ > >>>>> : IMM_MODE (value), \ > >>>>> "i" (offsetof (struct pthread, member))); \ > >>>>> + else if (__builtin_constant_p (value) \ > >>>>> + && (int64_t) (int32_t) (uintptr_t) value != (uintptr_t) value) \ > >>>>> + asm volatile ("movq %0,%%fs:%P1" : \ > >>>>> + : "r" (value), \ > >>>>> + "i" (offsetof (struct pthread, member))); \ > >>>> > >>>> (1) Move conditional into 'else /* 8 */' section. > >>>> > >>>> The blocks of conditionals are predicated on the size of the member we are > >>>> about to write to. > >>>> > >>>> In the block below... > >>>> > >>>>> else /* 8 */ \ > >>>> > >>>> ... here, we are about to write value into a member that is size 8. > >>>> > >>>> Your code changes the logical construction of the code, but in way that makes > >>>> it more difficult to understand. > >>>> > >>>> We previously had: > >>>> > >>>> if (sizeof() == 1) > >>>> > >>>> else if (sizeof() == 4) > >>>> > >>>> else /* Assume 8 */ > >>>> > >>>> In your case we must already be in the 'else /* Assume 8 */' because otherwise > >>>> we've be writing a 64-bit constant into a < 64-bit structure member. > >>>> > >>>> I think we should put your code into the else clause. > >>>> > >>>> 272 else /* 8 */ \ > >>>> 273 { \ > >>>> > >>>> if (__builtin_constant_p (value) > >>>> && ([the value is a >32-bit constant]) > >>>> asm volatile ([use movq reg64, mem64]); > >>>> else > >>>> > >>>> 274 asm volatile ("movq %q0,%%fs:%P1" : \ > >>>> 275 : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > >>>> 276 "i" (offsetof (struct pthread, member))); \ > >>>> 277 }}) > >>>> > >>>> (2) What if gcc can't prove it's constant? > >>>> > >>>> If the constant is >32-bit, but gcc can't prove it's constant, then don't we > >>>> try to put a >32-bit constant into a 32-bit immediate? > >>>> > >>>> Shouldn't the code be structured the other way around? > >>>> > >>>> e.g. > >>>> > >>>> else /* 8 */ > >>>> { > >>>> if (__builtin_constant_p (value) > >>>> && ([the value is a <= 32-bit constant]) > >>>> asm volatile ([use movq imm32, mem64]); > >>>> else > >>>> asm volatile ([use movq reg64, mem64]); > >>>> } > >>>> > >>>> This way the code is always correct? > >>> > >>> I changed it to > >>> > >>> if (!__builtin_constant_p (value) \ > >>> || (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value) \ > >>> asm volatile ("movq %q0,%%fs:%P1" : \ > >>> : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > >>> "i" (offsetof (struct pthread, member))); \ > >>> else \ > >>> asm volatile ("movq %0,%%fs:%P1" : \ > >>> : "r" (value), \ > >>> "i" (offsetof (struct pthread, member))); \ > >>> > >>>>> { \ > >>>>> asm volatile ("movq %q0,%%fs:%P1" : \ > >>>>> @@ -294,6 +299,12 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > >>>>> : IMM_MODE (value), \ > >>>>> "i" (offsetof (struct pthread, member[0])), \ > >>>>> "r" (idx)); \ > >>>>> + else if (__builtin_constant_p (value) \ > >>>>> + && (int64_t) (int32_t) (uintptr_t) value != (uintptr_t) value) \ > >>>>> + asm volatile ("movq %0,%%fs:%P1(,%q2,8)" : \ > >>>>> + : "r" (value), \ > >>>>> + "i" (offsetof (struct pthread, member[0])), \ > >>>>> + "r" (idx)); \ > >>>>> else /* 8 */ \ > >>>>> { \ > >>>>> asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ > >>>>> > >>>> > >>> > >>> Here is the v2 patch. OK for master? > >>> > >>> Thanks. > >>> > >> > >>> From 4fbc9ab67933d662506a01658d4c81a922e50fdf Mon Sep 17 00:00:00 2001 > >>> From: "H.J. Lu" <hjl.tools@gmail.com> > >>> Date: Fri, 8 Jan 2021 15:38:14 -0800 > >>> Subject: [PATCH v2] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64 > >>> > >>> Since there is only "movq imm32s, mem64" and no "movq imm64, mem64", use > >>> "movq reg64, mem64" to store 64-bit constant. > >>> --- > >>> sysdeps/x86_64/nptl/tls.h | 27 ++++++++++++++++++++------- > >>> 1 file changed, 20 insertions(+), 7 deletions(-) > >>> > >>> diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h > >>> index 20f0958780..0dbd66209c 100644 > >>> --- a/sysdeps/x86_64/nptl/tls.h > >>> +++ b/sysdeps/x86_64/nptl/tls.h > >>> @@ -271,9 +271,15 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > >>> "i" (offsetof (struct pthread, member))); \ > >>> else /* 8 */ \ > >>> { \ > >>> - asm volatile ("movq %q0,%%fs:%P1" : \ > >>> - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > >>> - "i" (offsetof (struct pthread, member))); \ > >>> + if (!__builtin_constant_p (value) \ > >> > >> Whis is this a "!__builtin_constant_p?" > >> > >> I would have expected: > >> > >> if ([the value is a constant a therefore known quantity] > >> || [it is a 32-bit value]) > > > > IMM_MODE constraint is valid only if VALUE isn't a constant or > > is a signed 32-bit constant. > > > >> Perhaps a quick single line comment here explaining the conditionals would help? > > > > Done. > > > > Here is the v3 patch with comments. OK for master? > > No, this still doesn't make logical sense to me. > > See my comments below. > > > From 0a5d266206be231ab11f3cfa0e213db1e04cd7bd Mon Sep 17 00:00:00 2001 > > From: "H.J. Lu" <hjl.tools@gmail.com> > > Date: Fri, 8 Jan 2021 15:38:14 -0800 > > Subject: [PATCH v3] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64 > > > > Since there is only "movq imm32s, mem64" and no "movq imm64, mem64", use > > "movq reg64, mem64" to store 64-bit constant. > > --- > > sysdeps/x86_64/nptl/tls.h | 31 ++++++++++++++++++++++++------- > > 1 file changed, 24 insertions(+), 7 deletions(-) > > > > diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h > > index 20f0958780..acea951d49 100644 > > --- a/sysdeps/x86_64/nptl/tls.h > > +++ b/sysdeps/x86_64/nptl/tls.h > > @@ -271,9 +271,17 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > > "i" (offsetof (struct pthread, member))); \ > > else /* 8 */ \ > > { \ > > - asm volatile ("movq %q0,%%fs:%P1" : \ > > - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > > - "i" (offsetof (struct pthread, member))); \ > > + /* NB: IMM_MODE constraint is valid only if VALUE isn't a constant \ > > + or is a signed 32-bit constant. */ \ > > We are trying to gate this asm volatile so it is only used by the compiler > when the immediate is known to be 32-bit wide. > > The old code was using IMM_MODE, which resolves to "nr" which should as a > constraint attempt to pass in a compile-time constant 32-bit value. My > understanding is that this constraint could fail to be met and the we get > a compile-time failure? > > The value of !__builtin_constant_p only tells you that the value is not a > constant. What prevents that value from being a 64-bit register with a 64-bit > value which can't be encoded via 'nr' with movq? > > Why isn't the right solution? > > if (__builtin_constant_p (value) > && (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value)) > /* The value is constant and known to be <= 32-bit immediate value. > In this case we allow the compiler to optimize and use movq with > an immediate value. */ > ... > else > /* The value is not known and so we must assume it is at worst a 64-bit value. > We can't optimize this and so we must use a register for the move. */ > ... > Fixed. Here is the v4 patch. OK for master? Thanks.
Comments
On 3/15/21 9:29 AM, H.J. Lu wrote: > Here is the v4 patch. OK for master? Let me start from the beginning, just to clarify a few things for my review. The original sequence was this: asm volatile ("movq %0,%%fs:%P1" : : IMM_MODE ((uint64_t) cast_to_integer (value)), "i" (offsetof (struct pthread, member))); With IMM_MODE being 'nr'/'ir' and allows: i/n - immediate integer operand r - register operand You attempt to write a 64-bit constant to the TCB and the above code fails. Does gcc attempt to encode a 64-bit immediate into %0 and the assembler fails? What was the error? Then we try to fix this with the new sequence: asm volatile ("movq %q0,%%fs:%P1" : : "i" ((uint64_t) cast_to_integer (value)), "i" (offsetof (struct pthread, member))); Note that "%q0" is a machine constraint for any register. This enforces only "i" (immediate integer operand) but requires the compiler pick a register with the machine constraint for "%q0", so you can have 64-bit constants but the compiler must arrange (via more machine instructions to get the constant in into a 64-bit register). Your v4 follows: > From d3854da28e1cfc2544226629b3b85ad6e2d6f4d4 Mon Sep 17 00:00:00 2001 > From: "H.J. Lu" <hjl.tools@gmail.com> > Date: Fri, 8 Jan 2021 15:38:14 -0800 > Subject: [PATCH v4] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64 > > Since there is only "movq imm32s, mem64" and no "movq imm64, mem64", use > "movq reg64, mem64" to store 64-bit constant> --- > sysdeps/x86_64/nptl/tls.h | 33 ++++++++++++++++++++++++++------- > 1 file changed, 26 insertions(+), 7 deletions(-) > > diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h > index 20f0958780..2a4739df64 100644 > --- a/sysdeps/x86_64/nptl/tls.h > +++ b/sysdeps/x86_64/nptl/tls.h > @@ -271,9 +271,18 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > "i" (offsetof (struct pthread, member))); \ > else /* 8 */ \ > { \ > - asm volatile ("movq %q0,%%fs:%P1" : \ > - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > - "i" (offsetof (struct pthread, member))); \ > + /* The value is constant and known to be <= 32-bit immediate value. \ > + In this case we allow the compiler to optimize and use movq with \ > + an immediate value. */ \ > + if (__builtin_constant_p (value) \ > + && (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value) \ Note that I made a typo on my last review. My intent was to write this: /* The value is constant and known to be <= 32-bit immediate value. \ In this case we allow the compiler to optimize and use movq with \ an immediate value. */ \ if (__builtin_constant_p (value) && (int64_t) (int32_t) (uintptr_t) value != (uintptr_t) value)) asm volatile ("movq %0,%%fs:%P1" : \ : IMM_MODE ((uint64_t) cast_to_integer (value)), \ "i" (offsetof (struct pthread, member))); \ else /* The value is not known and so we must assume it is at worst a 64-bit value. We can't optimize this and so we must use a register for the move. */ asm volatile ("movq %q0,%%fs:%P1" : \ : "i" ((uint64_t) cast_to_integer (value)), \ "i" (offsetof (struct pthread, member))); \ So in the case you write a 64-bit constant you get the else case. But in the case you have normal known 32-bit values you get the movq with a imm32s. Does that work? Can you please verify that you get the first case for all the normal 32-bit constants? Can you please verify that you get the second for the 64-bit constant write? > + asm volatile ("movq %q0,%%fs:%P1" : \ > + : "i" ((uint64_t) cast_to_integer (value)), \ > + "i" (offsetof (struct pthread, member))); \ > + else \ > + asm volatile ("movq %0,%%fs:%P1" : \ > + : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > + "i" (offsetof (struct pthread, member))); \ > }}) > > > @@ -296,10 +305,20 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, > "r" (idx)); \ > else /* 8 */ \ > { \ > - asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ > - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > - "i" (offsetof (struct pthread, member[0])), \ > - "r" (idx)); \ > + /* The value is constant and known to be <= 32-bit immediate value. \ > + In this case we allow the compiler to optimize and use movq with \ > + an immediate value. */ \ > + if (__builtin_constant_p (value) \ > + && (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value) \ > + asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ > + : "i" ((uint64_t) cast_to_integer (value)), \ > + "i" (offsetof (struct pthread, member[0])), \ > + "r" (idx)); \ > + else \ > + asm volatile ("movq %0,%%fs:%P1(,%q2,8)" : \ > + : IMM_MODE ((uint64_t) cast_to_integer (value)), \ > + "i" (offsetof (struct pthread, member[0])), \ > + "r" (idx)); \ > }}) > > > -- > 2.30.2 >
On Mär 15 2021, Carlos O'Donell via Libc-alpha wrote: > Then we try to fix this with the new sequence: > > asm volatile ("movq %q0,%%fs:%P1" : > : "i" ((uint64_t) cast_to_integer (value)), > "i" (offsetof (struct pthread, member))); > > Note that "%q0" is a machine constraint for any register. An operand modifier isn't a constraint. It does not change what the compiler matches for the operand, it only modifies the way the operand is output. 'q' has no meaning for an operand matched by the 'i' constraint, since that is never a register. Andreas.
From d3854da28e1cfc2544226629b3b85ad6e2d6f4d4 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" <hjl.tools@gmail.com> Date: Fri, 8 Jan 2021 15:38:14 -0800 Subject: [PATCH v4] x86_64: Update THREAD_SETMEM/THREAD_SETMEM_NC for IMM64 Since there is only "movq imm32s, mem64" and no "movq imm64, mem64", use "movq reg64, mem64" to store 64-bit constant. --- sysdeps/x86_64/nptl/tls.h | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h index 20f0958780..2a4739df64 100644 --- a/sysdeps/x86_64/nptl/tls.h +++ b/sysdeps/x86_64/nptl/tls.h @@ -271,9 +271,18 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, "i" (offsetof (struct pthread, member))); \ else /* 8 */ \ { \ - asm volatile ("movq %q0,%%fs:%P1" : \ - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ - "i" (offsetof (struct pthread, member))); \ + /* The value is constant and known to be <= 32-bit immediate value. \ + In this case we allow the compiler to optimize and use movq with \ + an immediate value. */ \ + if (__builtin_constant_p (value) \ + && (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value) \ + asm volatile ("movq %q0,%%fs:%P1" : \ + : "i" ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct pthread, member))); \ + else \ + asm volatile ("movq %0,%%fs:%P1" : \ + : IMM_MODE ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct pthread, member))); \ }}) @@ -296,10 +305,20 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80, "r" (idx)); \ else /* 8 */ \ { \ - asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ - : IMM_MODE ((uint64_t) cast_to_integer (value)), \ - "i" (offsetof (struct pthread, member[0])), \ - "r" (idx)); \ + /* The value is constant and known to be <= 32-bit immediate value. \ + In this case we allow the compiler to optimize and use movq with \ + an immediate value. */ \ + if (__builtin_constant_p (value) \ + && (int64_t) (int32_t) (uintptr_t) value == (uintptr_t) value) \ + asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \ + : "i" ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ + else \ + asm volatile ("movq %0,%%fs:%P1(,%q2,8)" : \ + : IMM_MODE ((uint64_t) cast_to_integer (value)), \ + "i" (offsetof (struct pthread, member[0])), \ + "r" (idx)); \ }}) -- 2.30.2