hmmer-3.3/src/fm_sse.c
/* Function:  fm_initConfig()
 * Purpose:   Initialize vector masks used in SSE FMindex implementation
 */
fm_initConfig()
Purpose:   Initialize vector masks used in SSE FMindex implementation
fm_initConfig () Purpose : Initialize vector masks used in SSE FMindex implementation
int
fm_configInit( FM_CFG *cfg, ESL_GETOPTS *go )
{
  fm_initConfigGeneric(cfg, go);
#if defined (eslENABLE_SSE)
  int i,j;
  int trim_chunk_count;
  int status;
  cfg->fm_allones_v = _mm_set1_epi8(0xff);
  cfg->fm_neg128_v  = _mm_set1_epi8((int8_t) -128);
  cfg->fm_zeros_v = _mm_set1_epi8((int8_t) 0x00);      
  cfg->fm_m0f     = _mm_set1_epi8((int8_t) 0x0f);      
  if (cfg->meta->alph_type == fm_DNA) {
    cfg->fm_m01 = _mm_set1_epi8((int8_t) 0x55);   
    cfg->fm_m11 = _mm_set1_epi8((int8_t) 0x03);  
  }
  cfg->fm_chars_v         = NULL;
  ESL_ALLOC (cfg->fm_chars_mem, cfg->meta->alph_size * sizeof(__m128)  + 15 ); 
  cfg->fm_chars_v =   (__m128i *) (((unsigned long int)(cfg->fm_chars_mem) + 15) & (~0xf));   
  for (i=0; i<cfg->meta->alph_size; i++) {
    int8_t c = i;
    if (cfg->meta->alph_type == fm_DNA) {
      c |= i<<2;
      c |= i<<4;
      c |= i<<6;
    } 
    cfg->fm_chars_v[i] = _mm_set1_epi8(c);
  }
   if (cfg->meta->alph_type == fm_DNA)
     trim_chunk_count = 64; 
   else 
     trim_chunk_count = 16; 
  cfg->fm_masks_v         = NULL;
  cfg->fm_reverse_masks_v = NULL;
  ESL_ALLOC (cfg->fm_masks_mem, (1+trim_chunk_count) *sizeof(__m128)  + 15 ); 
     cfg->fm_masks_v =   (__m128i *) (((unsigned long int)(cfg->fm_masks_mem) + 15) & (~0xf));   
  ESL_ALLOC (cfg->fm_reverse_masks_mem, (1+trim_chunk_count) *sizeof(__m128)  + 15 ); 
     cfg->fm_reverse_masks_v =   (__m128i *) (((unsigned long int)(cfg->fm_reverse_masks_mem) + 15) & (~0xf));   
  {
    byte_m128 arr;
    arr.m128 = cfg->fm_allones_v;
    for (i=trim_chunk_count-1; i>0; i--) {
      int byte_mask=0xff; 
      int byte_i = (i-1)/(trim_chunk_count/16);
      if (cfg->meta->alph_type == fm_DNA) {
        switch (i&0x03) {
          case 1:
            byte_mask = 0xc0; 
            break;
          case 2:
            byte_mask = 0xf0; 
            break;
          case 3:
            byte_mask = 0xfc; 
            break;
          default:
            break;
        }
      }
      arr.bytes[byte_i] = byte_mask; 
      for (j=byte_i+1; j<16; j++) {
        arr.bytes[j] = 0x0;
      }
      cfg->fm_masks_v[i]                           = *(__m128i*)(&(arr.m128));
      cfg->fm_reverse_masks_v[trim_chunk_count-i]  = _mm_andnot_si128(cfg->fm_masks_v[i], cfg->fm_allones_v );
    }
  }
#endif 
  return eslOK;
#if defined (eslENABLE_SSE)
ERROR:
  if (cfg->fm_chars_mem)         free(cfg->fm_chars_mem);
  if (cfg->fm_masks_mem)         free(cfg->fm_masks_mem);
  if (cfg->fm_reverse_masks_mem) free(cfg->fm_reverse_masks_mem);
  esl_fatal("Error allocating memory in initGlobals\n");
  return eslFAIL;
#endif
}
int fm_configInit ( FM_CFG * cfg , ESL_GETOPTS * go ) { fm_initConfigGeneric ( cfg , go ) ; #if defined ( eslENABLE_SSE ) int i , j ; int trim_chunk_count ; int status ; cfg -> fm_allones_v = _mm_set1_epi8 ( 0xff ) ; cfg -> fm_neg128_v = _mm_set1_epi8 ( ( int8_t ) -128 ) ; cfg -> fm_zeros_v = _mm_set1_epi8 ( ( int8_t ) 0x00 ) ; cfg -> fm_m0f = _mm_set1_epi8 ( ( int8_t ) 0x0f ) ; if ( cfg -> meta -> alph_type == fm_DNA ) { cfg -> fm_m01 = _mm_set1_epi8 ( ( int8_t ) 0x55 ) ; cfg -> fm_m11 = _mm_set1_epi8 ( ( int8_t ) 0x03 ) ; } cfg -> fm_chars_v = NULL ; ESL_ALLOC ( cfg -> fm_chars_mem , cfg -> meta -> alph_size * sizeof ( __m128 ) + 15 ) ; cfg -> fm_chars_v = ( __m128i * ) ( ( ( unsigned long int ) ( cfg -> fm_chars_mem ) + 15 ) & ( ~ 0xf ) ) ; for ( i = 0 ; i < cfg -> meta -> alph_size ; i ++ ) { int8_t c = i ; if ( cfg -> meta -> alph_type == fm_DNA ) { c |= i << 2 ; c |= i << 4 ; c |= i << 6 ; } cfg -> fm_chars_v [ i ] = _mm_set1_epi8 ( c ) ; } if ( cfg -> meta -> alph_type == fm_DNA ) trim_chunk_count = 64 ; else trim_chunk_count = 16 ; cfg -> fm_masks_v = NULL ; cfg -> fm_reverse_masks_v = NULL ; ESL_ALLOC ( cfg -> fm_masks_mem , ( 1 + trim_chunk_count ) * sizeof ( __m128 ) + 15 ) ; cfg -> fm_masks_v = ( __m128i * ) ( ( ( unsigned long int ) ( cfg -> fm_masks_mem ) + 15 ) & ( ~ 0xf ) ) ; ESL_ALLOC ( cfg -> fm_reverse_masks_mem , ( 1 + trim_chunk_count ) * sizeof ( __m128 ) + 15 ) ; cfg -> fm_reverse_masks_v = ( __m128i * ) ( ( ( unsigned long int ) ( cfg -> fm_reverse_masks_mem ) + 15 ) & ( ~ 0xf ) ) ; { byte_m128 arr ; arr . m128 = cfg -> fm_allones_v ; for ( i = trim_chunk_count - 1 ; i > 0 ; i -- ) { int byte_mask = 0xff ; int byte_i = ( i - 1 ) / ( trim_chunk_count / 16 ) ; if ( cfg -> meta -> alph_type == fm_DNA ) { switch ( i & 0x03 ) { case 1 : byte_mask = 0xc0 ; break ; case 2 : byte_mask = 0xf0 ; break ; case 3 : byte_mask = 0xfc ; break ; default : break ; } } arr . bytes [ byte_i ] = byte_mask ; for ( j = byte_i + 1 ; j < 16 ; j ++ ) { arr . bytes [ j ] = 0x0 ; } cfg -> fm_masks_v [ i ] = * ( __m128i * ) ( & ( arr . m128 ) ) ; cfg -> fm_reverse_masks_v [ trim_chunk_count - i ] = _mm_andnot_si128 ( cfg -> fm_masks_v [ i ] , cfg -> fm_allones_v ) ; } } #endif return eslOK ; #if defined ( eslENABLE_SSE ) ERROR : if ( cfg -> fm_chars_mem ) free ( cfg -> fm_chars_mem ) ; if ( cfg -> fm_masks_mem ) free ( cfg -> fm_masks_mem ) ; if ( cfg -> fm_reverse_masks_mem ) free ( cfg -> fm_reverse_masks_mem ) ; esl_fatal ( " \n " ) ; return eslFAIL ; #endif }
Function:  fm_initConfig()
 Purpose:   Initialize vector masks used in SSE FMindex implementation
Function : fm_initConfig () Purpose : Initialize vector masks used in SSE FMindex implementation
//00 00 00 00 //00 00 11 11 //01 01 01 01 //00 00 00 11 //set up an array of vectors, one for each character in the alphabet // +15 for manual 16-byte alignment, which matters for SIMD stuff /* align vector memory on 16-byte boundaries */ // need 4 copies per byte //else, just leave it on the right-most bits /* this is a collection of masks used to clear off the left- or right- part
   *  of a register when we shouldn't be counting the whole thing
   * Incrementally chew off the 1s in chunks of 2 (for DNA) or 4 (for DNA_full)
   * from the right side, and stick each result into an element of a __m128 array
   */ //2-bit steps // then cfg->meta->alph_type == fm_AMINO, we suppose //8-bit steps //chars_per_vector = 128/meta->charBits; // +15 for manual 16-byte alignment, which matters for SIMD stuff /* align vector memory on 16-byte boundaries */ // +15 for manual 16-byte alignment, which matters for SIMD stuff /* align vector memory on 16-byte boundaries */ //11 11 11 11 //11 00 00 00 //11 11 00 00 //11 11 11 00 //chew off the appropriate number of bits // eslENABLE_SSE /*
  if (cfg->meta->alph_type == fm_DNA_full) {
    cfg->fm_masks_v[16]          = cfg->fm_allones_v;
    cfg->fm_reverse_masks_v[16]  = cfg->fm_allones_v;
  }
*/