Информация об изменениях

Сообщение Re[5]: Быстро проверить на BCD от 27.06.2017 16:30

Изменено 27.06.2017 16:35 rameel

Re[5]: Быстро проверить на BCD
Здравствуйте, tyomchick, Вы писали:

T>Проверял я на С# .


Текущий JIT не достаточно прозорлив в отличие от компиляторов C++, которые умеют вот такое:
bool is_bcd1(unsigned int val)
{
  unsigned int possible_non_bcd = val & 0x88888888; // 8,9,A,B,C,D,E,F
  
  if ((possible_non_bcd >> 1) & val)
    return false; // C, D, E, F


  if ((possible_non_bcd >> 2) & val)
    return false; // A, B

  return true;
}

превратить вот в такое:
bool is_bcd3(unsigned int val)
{
  unsigned int possible_non_bcd = val & 0x88888888; // 8,9,A,B,C,D,E,F
  
  return (((possible_non_bcd >> 1) | (possible_non_bcd >> 2)) & val) == 0;
}


и сгенерировать одинаковый код. Вот пруф: https://godbolt.org/g/KJ8XLo

Для джита же эту оптимизацию нужно провести вручную. Пруф: SharpLab

; C++
mov     eax, edi
and     eax, -2004318072
mov     edx, eax
shr     eax, 2
shr     edx
or      eax, edx
test    eax, edi
sete    al
ret

; JIT x86
L0000: mov edx, ecx
L0002: and edx, 0x88888888
L0008: mov eax, edx
L000a: shr eax, 1
L000c: shr edx, 0x2
L000f: or eax, edx
L0011: and eax, ecx
L0013: setz al
L0016: movzx eax, al
L0019: ret
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[5]: Быстро проверить на BCD
Здравствуйте, tyomchick, Вы писали:

T>Проверял я на С# .


Текущий JIT не достаточно прозорлив в отличие от компиляторов C++, которые умеют вот такое:
bool is_bcd1(unsigned int val)
{
  unsigned int possible_non_bcd = val & 0x88888888; // 8,9,A,B,C,D,E,F
  
  if ((possible_non_bcd >> 1) & val)
    return false; // C, D, E, F


  if ((possible_non_bcd >> 2) & val)
    return false; // A, B

  return true;
}

превратить вот в такое:
bool is_bcd3(unsigned int val)
{
  unsigned int possible_non_bcd = val & 0x88888888; // 8,9,A,B,C,D,E,F
  
  return (((possible_non_bcd >> 1) | (possible_non_bcd >> 2)) & val) == 0;
}


и сгенерировать одинаковый код. Вот пруф: https://godbolt.org/g/KJ8XLo

Для джита же эту оптимизацию нужно провести вручную.
public static bool is_bcd2(uint val)
{
    uint possible_non_bcd = val & 0x88888888; // 8,9,A,B,C,D,E,F

    return (((possible_non_bcd >> 1) | (possible_non_bcd >> 2)) & val) == 0;
}


Пруф: SharpLab

; C++
mov     eax, edi
and     eax, -2004318072
mov     edx, eax
shr     eax, 2
shr     edx
or      eax, edx
test    eax, edi
sete    al
ret

; JIT x86
mov   edx, ecx
and   edx, 0x88888888
mov   eax, edx
shr   eax, 1
shr   edx, 0x2
or    eax, edx
and   eax, ecx
setz  al
movzx eax, al
ret
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>