llvm/llvm-project

[X86][SSE] Recognise v2i64 comparison patterns

Open

#32.961 aberto em 27 de jun. de 2017

Ver no GitHub
 (9 comments) (0 reactions) (1 assignee)C++ (10.782 forks)batch import
backend:X86bugzillaconfirmedgood first issuellvm:instcombine

Métricas do repositório

Stars
 (26.378 stars)
Métricas de merge de PR
 (Mesclagem média 1d 2h) (1.000 fundiu PRs em 30d)

Description

Bugzilla Link 33614
Version trunk
OS Windows NT
CC @nikic,@rotateright

Extended Description

Before SSE41/SSE42, the only way to compare eq/gt v2i64 vectors was to use the v4i32 intrinsics:

__m128i alt_cmpeq_epi64(__m128i a, __m128i b) {
  __m128i c = _mm_cmpeq_epi32(a, b);
  return _mm_and_si128( c, _mm_shuffle_epi32( c, _MM_SHUFFLE(2,3,0,1) ) );
}

__m128i alt_cmpgt_epi64(__m128i a, __m128i b) {
  __m128i flip = _mm_setr_epi32( 0x80000000,0x00000000,0x80000000,0x00000000 );
  a = _mm_xor_si128( a, flip );
  b = _mm_xor_si128( b, flip );
  __m128i gt = _mm_cmpgt_epi32( a, b );
  __m128i gt0 = _mm_shuffle_epi32( gt, _MM_SHUFFLE(2,2,0,0) );
  __m128i gt1 = _mm_shuffle_epi32( gt, _MM_SHUFFLE(3,3,1,1) );
  __m128i eq = _mm_cmpeq_epi32( a, b );
  __m128i eq0 = _mm_shuffle_epi32( eq, _MM_SHUFFLE(3,3,1,1) );
  return _mm_or_si128( _mm_and_si128( gt0, eq0 ), gt1 );
}


__m128i alt_cmpgt_epu64(__m128i a, __m128i b) {
  __m128i flip = _mm_set1_epi32( 0x80000000 );
  a = _mm_xor_si128( a, flip );
  b = _mm_xor_si128( b, flip );
  __m128i gt = _mm_cmpgt_epi32( a, b );
  __m128i gt0 = _mm_shuffle_epi32( gt, _MM_SHUFFLE(2,2,0,0) );
  __m128i gt1 = _mm_shuffle_epi32( gt, _MM_SHUFFLE(3,3,1,1) );
  __m128i eq = _mm_cmpeq_epi32( a, b );
  __m128i eq0 = _mm_shuffle_epi32( eq, _MM_SHUFFLE(3,3,1,1) );
  return _mm_or_si128( _mm_and_si128( gt0, eq0 ), gt1 );
}

Resulting in quite a bit of legacy code that still uses this (I've only seen this in __m128i code). We should be trying to simplify this where possible.

Guia do colaborador