mirror of https://github.com/YosysHQ/abc.git
Performance improvements of ACD 66
This commit is contained in:
parent
7b74810047
commit
0e471e3ff8
|
|
@ -145,18 +145,10 @@ private:
|
|||
best_multiplicity = UINT32_MAX;
|
||||
best_free_set = UINT32_MAX;
|
||||
|
||||
/* array of functions to compute the column multiplicity */
|
||||
std::function<uint32_t( STT const& tt )> column_multiplicity_fn[5] = {
|
||||
[this]( STT const& tt ) { return column_multiplicity<1u>( tt ); },
|
||||
[this]( STT const& tt ) { return column_multiplicity<2u>( tt ); },
|
||||
[this]( STT const& tt ) { return column_multiplicity<3u>( tt ); },
|
||||
[this]( STT const& tt ) { return column_multiplicity5<4u>( tt ); },
|
||||
[this]( STT const& tt ) { return column_multiplicity5<5u>( tt ); } };
|
||||
|
||||
/* find AC decompositions with minimal multiplicity */
|
||||
for ( uint32_t i = num_vars - 6; i <= 5 && i <= ps.max_free_set_vars; ++i )
|
||||
{
|
||||
if ( find_decomposition_bs( i, column_multiplicity_fn[i - 1] ) )
|
||||
if ( find_decomposition_bs( i ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -176,81 +168,40 @@ private:
|
|||
local_extend_to( start_tt, num_vars );
|
||||
}
|
||||
|
||||
template<uint32_t free_set_size>
|
||||
uint32_t column_multiplicity( STT tt )
|
||||
uint32_t column_multiplicity( STT const& tt, uint32_t free_set_size )
|
||||
{
|
||||
uint64_t multiplicity_set[4] = { 0u, 0u, 0u, 0u };
|
||||
uint32_t multiplicity = 0;
|
||||
assert( free_set_size <= 5 );
|
||||
|
||||
uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
|
||||
uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F };
|
||||
uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 };
|
||||
|
||||
/* supports up to 64 values of free set (256 for |FS| == 3)*/
|
||||
static_assert( free_set_size <= 3, "Wrong free set size for method used, expected le 3" );
|
||||
|
||||
/* extract iset functions */
|
||||
auto it = std::begin( tt );
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
|
||||
{
|
||||
multiplicity_set[( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] );
|
||||
*it >>= ( 1u << free_set_size );
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
multiplicity = __builtin_popcountl( multiplicity_set[0] );
|
||||
|
||||
if ( free_set_size == 3 )
|
||||
{
|
||||
multiplicity += __builtin_popcountl( multiplicity_set[1] );
|
||||
multiplicity += __builtin_popcountl( multiplicity_set[2] );
|
||||
multiplicity += __builtin_popcountl( multiplicity_set[3] );
|
||||
}
|
||||
|
||||
return multiplicity;
|
||||
}
|
||||
|
||||
template<uint32_t free_set_size>
|
||||
uint32_t column_multiplicity5( STT tt )
|
||||
{
|
||||
uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
|
||||
uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF };
|
||||
|
||||
static_assert( free_set_size == 5 || free_set_size == 4, "Wrong free set size for method used, expected of 4 or 5" );
|
||||
|
||||
uint64_t shift = UINT64_C( 1 ) << free_set_size;
|
||||
uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1;
|
||||
uint32_t cofactors[4];
|
||||
uint32_t size = 0;
|
||||
uint64_t prev = -1;
|
||||
std::array<uint32_t, 64> multiplicity_set;
|
||||
|
||||
/* extract iset functions */
|
||||
auto it = std::begin( tt );
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
uint64_t sub = *it;
|
||||
for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
|
||||
{
|
||||
uint32_t fs_fn = static_cast<uint32_t>( *it & masks[free_set_size] );
|
||||
if ( fs_fn != prev )
|
||||
uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
|
||||
uint32_t k;
|
||||
for ( k = 0; k < size; ++k )
|
||||
{
|
||||
multiplicity_set[size++] = fs_fn;
|
||||
prev = fs_fn;
|
||||
if ( fs_fn == cofactors[k] )
|
||||
break;
|
||||
}
|
||||
*it >>= ( 1u << free_set_size );
|
||||
if ( k == 4 )
|
||||
return 5;
|
||||
if ( k == size )
|
||||
cofactors[size++] = fs_fn;
|
||||
sub >>= shift;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
std::sort( multiplicity_set.begin(), multiplicity_set.begin() + size );
|
||||
|
||||
/* count unique */
|
||||
uint32_t multiplicity = 1;
|
||||
for ( auto i = 1u; i < size; ++i )
|
||||
{
|
||||
multiplicity += multiplicity_set[i] != multiplicity_set[i - 1] ? 1 : 0;
|
||||
}
|
||||
|
||||
return multiplicity;
|
||||
return size;
|
||||
}
|
||||
|
||||
inline bool combinations_next( uint32_t k, uint32_t* pComb, uint32_t* pInvPerm, STT& tt )
|
||||
|
|
@ -282,8 +233,7 @@ private:
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Fn>
|
||||
bool find_decomposition_bs( uint32_t free_set_size, Fn&& fn )
|
||||
bool find_decomposition_bs( uint32_t free_set_size )
|
||||
{
|
||||
STT tt = start_tt;
|
||||
|
||||
|
|
@ -301,7 +251,7 @@ private:
|
|||
best_free_set = free_set_size;
|
||||
do
|
||||
{
|
||||
uint32_t cost = fn( tt );
|
||||
uint32_t cost = column_multiplicity( tt, free_set_size );
|
||||
if ( cost == 2 )
|
||||
{
|
||||
best_tt = tt;
|
||||
|
|
@ -316,7 +266,7 @@ private:
|
|||
{
|
||||
/* look for a shared variable */
|
||||
best_multiplicity = cost;
|
||||
int res = check_shared_set2( tt );
|
||||
int res = check_shared_set( tt );
|
||||
|
||||
if ( res > 0 )
|
||||
{
|
||||
|
|
@ -336,136 +286,55 @@ private:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool check_shared_var( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit )
|
||||
bool check_shared_var( STT const& tt, uint32_t free_set_size, uint32_t shared_var )
|
||||
{
|
||||
uint64_t multiplicity_set[2][4] = { { 0u, 0u, 0u, 0u }, { 0u, 0u, 0u, 0u } };
|
||||
uint32_t multiplicity0 = 0, multiplicity1 = 0;
|
||||
assert( free_set_size <= 5 );
|
||||
|
||||
uint32_t const num_blocks = ( num_vars > 6 ) ? ( 1u << ( num_vars - 6 ) ) : 1;
|
||||
uint64_t constexpr masks_bits[] = { 0x0, 0x3, 0xF, 0x3F };
|
||||
uint64_t constexpr masks_idx[] = { 0x0, 0x0, 0x0, 0x3 };
|
||||
|
||||
/* supports up to 64 values of free set (256 for |FS| == 3)*/
|
||||
assert( free_set_size <= 3 );
|
||||
|
||||
uint64_t shift = UINT64_C( 1 ) << free_set_size;
|
||||
uint64_t mask = ( UINT64_C( 1 ) << shift ) - 1;
|
||||
uint32_t cofactors[2][4];
|
||||
uint32_t size[2] = { 0, 0 };
|
||||
uint32_t shared_var_shift = shared_var - free_set_size;
|
||||
|
||||
/* extract iset functions */
|
||||
uint64_t iteration_counter = 0;
|
||||
uint32_t iteration_counter = 0;
|
||||
auto it = std::begin( tt );
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
uint64_t sub = *it;
|
||||
for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
|
||||
{
|
||||
multiplicity_set[( iteration_counter >> shared_var_shift ) & 1][( *it >> 6 ) & masks_idx[free_set_size]] |= UINT64_C( 1 ) << ( *it & masks_bits[free_set_size] );
|
||||
*it >>= ( 1u << free_set_size );
|
||||
uint32_t fs_fn = static_cast<uint32_t>( sub & mask );
|
||||
uint32_t p = ( iteration_counter >> shared_var_shift ) & 1;
|
||||
uint32_t k;
|
||||
for ( k = 0; k < size[p]; ++k )
|
||||
{
|
||||
if ( fs_fn == cofactors[p][k] )
|
||||
break;
|
||||
}
|
||||
if ( k == 2 )
|
||||
return false;
|
||||
if ( k == size[p] )
|
||||
cofactors[p][size[p]++] = fs_fn;
|
||||
sub >>= shift;
|
||||
++iteration_counter;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
multiplicity0 = __builtin_popcountl( multiplicity_set[0][0] );
|
||||
multiplicity1 = __builtin_popcountl( multiplicity_set[1][0] );
|
||||
|
||||
if ( free_set_size == 3 )
|
||||
{
|
||||
multiplicity0 += __builtin_popcountl( multiplicity_set[0][1] );
|
||||
multiplicity0 += __builtin_popcountl( multiplicity_set[0][2] );
|
||||
multiplicity0 += __builtin_popcountl( multiplicity_set[0][3] );
|
||||
|
||||
multiplicity1 += __builtin_popcountl( multiplicity_set[1][1] );
|
||||
multiplicity1 += __builtin_popcountl( multiplicity_set[1][2] );
|
||||
multiplicity1 += __builtin_popcountl( multiplicity_set[1][3] );
|
||||
}
|
||||
|
||||
if ( multiplicity0 > multiplicity_limit || multiplicity1 > multiplicity_limit )
|
||||
return false;
|
||||
|
||||
best_multiplicity0 = multiplicity0;
|
||||
best_multiplicity1 = multiplicity1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool check_shared_var5( STT tt, uint32_t free_set_size, uint32_t shared_var, uint32_t multiplicity_limit )
|
||||
{
|
||||
uint32_t const num_blocks = 1u << ( num_vars - 6 );
|
||||
uint64_t constexpr masks[] = { 0x0, 0x3, 0xF, 0xFF, 0xFFFF, 0xFFFFFFFF };
|
||||
|
||||
assert( free_set_size == 5 || free_set_size == 4 );
|
||||
|
||||
uint32_t size[2] = { 0, 0 };
|
||||
uint64_t prev[2] = { UINT64_MAX, UINT64_MAX };
|
||||
std::array<uint32_t, 64> multiplicity_set[2];
|
||||
|
||||
uint32_t shared_var_shift = shared_var - free_set_size;
|
||||
|
||||
/* extract iset functions */
|
||||
uint64_t iteration_counter = 0;
|
||||
auto it = std::begin( tt );
|
||||
for ( auto i = 0u; i < num_blocks; ++i )
|
||||
{
|
||||
for ( auto j = 0; j < ( 64 >> free_set_size ); ++j )
|
||||
{
|
||||
uint32_t fs_fn = static_cast<uint32_t>( *it & masks[free_set_size] );
|
||||
uint32_t cofactor = ( iteration_counter >> shared_var_shift ) & 1;
|
||||
if ( fs_fn != prev[cofactor] )
|
||||
{
|
||||
multiplicity_set[cofactor][size[cofactor]++] = fs_fn;
|
||||
prev[cofactor] = fs_fn;
|
||||
}
|
||||
*it >>= ( 1u << free_set_size );
|
||||
++iteration_counter;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
std::sort( multiplicity_set[0].begin(), multiplicity_set[0].begin() + size[0] );
|
||||
|
||||
/* count unique in 0 cofactor */
|
||||
uint32_t multiplicity = 1;
|
||||
for ( auto i = 1u; i < size[0]; ++i )
|
||||
{
|
||||
multiplicity += multiplicity_set[0][i] != multiplicity_set[0][i - 1] ? 1 : 0;
|
||||
}
|
||||
|
||||
if ( multiplicity > multiplicity_limit )
|
||||
return false;
|
||||
|
||||
best_multiplicity0 = multiplicity;
|
||||
|
||||
std::sort( multiplicity_set[1].begin(), multiplicity_set[1].begin() + size[1] );
|
||||
|
||||
/* count unique in 1 cofactor */
|
||||
multiplicity = 1;
|
||||
for ( auto i = 1u; i < size[1]; ++i )
|
||||
{
|
||||
multiplicity += multiplicity_set[1][i] != multiplicity_set[1][i - 1] ? 1 : 0;
|
||||
}
|
||||
|
||||
best_multiplicity1 = multiplicity;
|
||||
|
||||
return multiplicity <= multiplicity_limit;
|
||||
}
|
||||
|
||||
int check_shared_set2( STT const& tt )
|
||||
inline int check_shared_set( STT const& tt )
|
||||
{
|
||||
/* find one shared set variable */
|
||||
for ( uint32_t i = best_free_set; i < num_vars; ++i )
|
||||
{
|
||||
/* check the multiplicity of cofactors */
|
||||
if ( best_free_set < 4 )
|
||||
if ( check_shared_var( tt, best_free_set, i ) )
|
||||
{
|
||||
if ( check_shared_var( tt, best_free_set, i, 2 ) )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( check_shared_var5( tt, best_free_set, i, 2 ) )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue