llvm/llvm-project

[X86][SSE] Recognise v2i64 comparison patterns

Open

#32 961 ouverte le 27 juin 2017

Voir sur GitHub
 (9 commentaires) (0 réactions) (1 assigné)C++ (10 782 forks)batch import
backend:X86bugzillaconfirmedgood first issuellvm:instcombine

Métriques du dépôt

Stars
 (26 378 stars)
Métriques de merge PR
 (Merge moyen 1j 2h) (1 000 PRs mergées en 30 j)

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.

Guide contributeur