Может ли x86 переупорядочить узкий магазин с более широкой загрузкой, которая полностью его содержит?

Руководство разработчика программного обеспечения для архитектуры Intel® 64 и IA-32 говорит:

8.2.3.4 Грузы могут быть переупорядочены с более ранними магазинами в разные места
Модель упорядочения памяти Intel-64 позволяет переупорядочивать нагрузку с более ранним хранилищем в другое место. Однако грузы не переупорядочиваются с магазинами в одном и том же месте.

Как насчет нагрузок, которые частично или полностью перекрывают предыдущие магазины, но не имеют одинаковый начальный адрес? (См. Конец этой статьи для конкретного случая)

Предположим, следующий C-подобный код:

// lock - pointer to an aligned int64 variable
// threadNum - integer in the range 0..7
// volatiles here just to show direct r/w of the memory as it was suggested in the comments
int TryLock(volatile INT64* lock, INT64 threadNum)
{
    if (0 != *lock)
        return 0;                           // another thread already had the lock

    ((volatile INT8*)lock)[threadNum] = 1;  // take the lock by setting our byte

    if (1LL << 8*threadNum != *lock)
    {   // another thread set its byte between our 1st and 2nd check.   unset ours
        ((volatile INT8*)lock)[threadNum] = 0;
        return 0;
    }

    return 1;
}

Или его эквивалент x64 asm:

; rcx - address of an aligned int64 variable
; rdx - integer in the range 0..7
TryLock PROC
cmp qword ptr [rcx], 0
jne @fail

mov r8, rdx
mov rax, 8
mul rdx

mov byte ptr [rcx+r8], 1

bts rdx, rax
cmp qword ptr [rcx], rdx
jz  @success

mov byte ptr [rcx+r8], 0

@fail:
mov rax, 0
ret

@success:
mov rax, 1
ret

Затем предположим, что TryLock одновременно выполняется в двух потоках:

INT64 lock = 0;

void Thread_1() {  TryLock(&lock, 1);  }
void Thread_5() {  TryLock(&lock, 5);  }
Вопрос:

((INT8*)lock)[1] = 1; а также((INT8*)lock)[5] = 1; магазины не находятся в том же месте, что и 64-битная загрузкаlock, Тем не менее, каждый из них полностью содержится в этой загрузке, поэтому считается ли это «одним и тем же местом»? Кажется невозможным, чтобы процессор мог это сделать.

Как насчет((INT8*)lock)[0] = 1? Адрес магазина тогда совпадает с адресом следующей загрузки. Являются ли эти операции «в том же месте», даже если предыдущий случай не был?

постскриптум обратите внимание, что вопрос не в коде C / Asm, а в поведении процессоров x86.

Ответы на вопрос(2)

Ваш ответ на вопрос